From a0a775ee8a23258144ea89fab46e0449bc12f10a Mon Sep 17 00:00:00 2001 From: Roman Krupnin Date: Tue, 28 Jul 2026 18:02:30 +0300 Subject: [PATCH] first working version after 30 years :) --- FDC.PAS | 479 +++++++++ HELPERS.PAS | 236 +++++ LD-ISDOS.PAS | 354 +++++++ LD-TRDOS.PAS | 363 +++++++ docs/8272.txt | 486 ++++++++++ docs/8272CMD.DOC | 144 +++ docs/8272FORM.DOC | 74 ++ docs/8272STAT.DOC | 109 +++ docs/I8272.DOC | 2194 ++++++++++++++++++++++++++++++++++++++++++ release/LD-ISDOS.EXE | Bin 0 -> 19776 bytes release/LD-TRDOS.EXE | Bin 0 -> 19920 bytes 11 files changed, 4439 insertions(+) create mode 100644 FDC.PAS create mode 100644 HELPERS.PAS create mode 100644 LD-ISDOS.PAS create mode 100644 LD-TRDOS.PAS create mode 100644 docs/8272.txt create mode 100644 docs/8272CMD.DOC create mode 100644 docs/8272FORM.DOC create mode 100644 docs/8272STAT.DOC create mode 100644 docs/I8272.DOC create mode 100644 release/LD-ISDOS.EXE create mode 100644 release/LD-TRDOS.EXE diff --git a/FDC.PAS b/FDC.PAS new file mode 100644 index 0000000..baf42c9 --- /dev/null +++ b/FDC.PAS @@ -0,0 +1,479 @@ +unit FDC; + +interface + +const + FDC_MAX_TRACK = 84; + + FDC_REG_SRA = $3F0; + FDC_REG_SRB = $3F1; + FDC_REG_DOR = $3F2; + {3F2H Запись: Регистр управления + ╓7┬6┬5┬4┬3┬2┬1┬0╖ + ·D C B A│ │ │ · + ╙─┴─┴─┴─┴╥┴╥┴─┴─╜ биты + ╚══╦══╝ · · ╚═╩═. 0-1: Выбор драйвера 0-3 (AT: бит 1 не исп.) + · · ╚═════. 2: 0=Сброс контроллера HГМД; 1=Разрешение контроллера + · ╚═══════. 3: 1=Разрешиить работу с DMA и прерываниями + ╚════════════. 4-7: Включить мотор драйвера. Если бит установлен то ВКЛ. + (AT: биты 6-7 игнорирует)} + FDC_REG_MSR = $3F4; + {3F4H Только-для чтения: Главный регистр статуса + ╓7┬6┬5┬4┬3┬2┬1┬0╖ + · │ │ │ │D C B A· + ╙╥┴╥┴╥┴╥┴─┴─┴─┴─╜ биты + · · · · ╚═════╩═. 0: Выбор драйвера (AT: биты 2-3 не использует) + · · · ╚═════════. 4: 1=Сигнал контроллера (Идет чтение или запись) + · · ╚═══════════. 5: 1=HЕ-DMA режим; 0=DMA режим включен + · ╚═════════════. 6: Сигнал управления: 1 = FDC═.CPU; 0 = CPU═.FDC + ╚═══════════════. 7: Запрос на Запись. 1=OK Передача/Прием ком или дан.} + + FDC_REG_DR = $3F5; + {3F5H Чтение/Запись: Регистр данных + Kмд Описание + ▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ + 0E6H Читать данные (Требует: 8 параметров; Pезультат : 7 параметров) + 0C5H Писать данные (Требует 8 параметров; Pезультат : 7 параметров) + 04DH Форматировать дорожку (Требует 5 параметров;Pезультат : 7 параметров) + 007H Рекалибровать (Требует 1 параметров; Pезультат : HЕТ) + 00FH Установить на дородку (Требует 2 параметров;Pезультат : HЕТ} + + FDC_REG_DIR = $3F7; + {3F7H ▌AT▐ Только-для чтения : Регистр сигнадов входа + ╓7┬6┬5┬4┬3┬2┬1┬0╖ + · │ │ · + ╙╥┴─┴─┴─┴─┴─┴─┴╥╜ бить + · ╚════╦════╝ ╚═. 0: 1= Выбрана двойная плотность; 0= Высокая плотность + · ╚════════. 1-6: Зарезервированы. + ╚═══════════════. 7: 1= Произошла замена дискеты} + + FDC_REG_CCR = $3F8; + {3F8H ▌AT▐ Запись : Регистр конфигурации + ╓7┬6┬5┬4┬3┬2┬1┬0╖ + · │ · + ╙─┴─┴─┴─┴─┴─┴─┴─╜ биты + ╚════╦════╝ ╚═╩═. 0-1: скорость пердачи данных + · 00=500 KBS, 01=300 KBS, 10=250 KBS, 11=зарезер. + ╚══════════. 2-7: Зарезервировано} + + FDC_CMD_READ_TRACK = $02; + FDC_CMD_SPECIFY = $03; + FDC_CMD_GET_STATUS3 = $04; + FDC_CMD_WRITE_DATA = $05; + FDC_CMD_READ_DATA = $06; + FDC_CMD_RECALIBRATE = $07; + FDC_CMD_WRITE_DELETED_DATA = $09; + FDC_CMD_READ_DELETED_DATA = $0C; + FDC_CMD_SEEK = $0F; + + { for FDC_CMD_READ_DATA } + FDC_HCMD_SK = $20; { BIT5: SK stands for Skip Deleted Data Addres Mark } + FDC_HCMD_MFM = $40; { BIT6: if high, MFM mode is selected } + FDC_HCMD_MT = $80; { BIT7: If MT is high, a multi-track operation is } + + FDC_SPEED_500 = $00; + FDC_SPEED_300 = $01; + FDC_SPEED_250 = $02; + FDC_SPEED_125 = $03; + FDC_SPEED_COUNT = $03; + + FDC_SECTOR_256 = 1; + FDC_SECTOR_512 = 2; + FDC_SECTOR_1024 = 3; + FDC_SECTOR_2048 = 4; + FDC_SECTOR_4096 = 5; + FDC_SECTOR_8192 = 6; + + { + +----------+-----------------+-----+-----+------+--------+----------------+ + | FORMAT | SECTOR SIZE | N | SC | GPL1| GPL2 | REMARKS | + +----------+-----------------+-----+-----+------+--------+----------------+ + | |256 | 01 | 1A | 0E | 36H |IBM Diskette 2D | + | |512 | 02 | 0F | 1B | 54H | | + | MFM Mode |1024 | 03 | 08 | 36H | 74H |IBM Diskette 2D | + | |2048 | 04 | 04 | __ | __ | | + | |4096 | 05 | 02 | __ | __ | | + | |8192 | 06 | 01 | __ | __ | | + +----------+-----------------+-----+-----+------+--------+----------------+ + Note : 1. GPL1 Suggested values of GPL in Read or Write Commands to avoid + splice point between data and ID field of contiguous sections. + + 2 GPL2, Suggested values of GPL in format command. + } + + FDC_OK = 0; + FDC_ERR_BAD_CONTROLLER = 1; + FDC_ERR_TIMEOUT = 2; + FDC_ERR_SEEK_ERROR = 3; + FDC_ERR_DRIVE_NOT_READY = 4; + FDC_ERR_END_OF_CYLINDER = 5; + FDC_ERR_BAD_SECTOR = 6; + FDC_ERR_DMA_ERROR = 7; + FDC_ERR_SECTOR_NOT_FOUND = 8; + FDC_ERR_WRITE_PROTECT = 9; + FDC_ERR_UNKNOWN = 10; + +type + TFDCBbuffer = array[1..8192] of byte; + +var + fdcBuf: TFDCBbuffer; + fdcIOError: byte; + fdcStatus: array[1..8] of byte; + +procedure fdcMotorOn(drv: byte); +procedure fdcMotorOff; + +procedure fdcRecalibrate(drv: byte); +procedure fdcSeek(drv, trck: byte); +procedure fdcSpecify; +procedure fdcReadSector(drv, track_id, head_id, sector_id, sector_size_id, last_sector_id: byte); + +procedure fdcInit(drv, sector_size_id: byte); +function fdcErrorStr(value: byte): string; +function fdcSpeedStr(value: byte): string; + +implementation + +uses + crt; + +{ HELPERS } + +{----------------------------------------------------------------------------} +function strr(value: longint): string; +var + r: string; +begin + str(value, r); + + strr:= r; +end; + +{----------------------------------------------------------------------------} +function TestBit(Num, Bit: byte): boolean; +const + Bits: array[0..7] of word = (1,2,4,8,16,32,64,128); +begin + TestBit:= (Num and Bits[Bit]) <> 0; +end; + +{----------------------------------------------------------------------------} +procedure IncPtr(var p: pointer; off: Word); +begin + asm + push ds + lds di,p + mov ax,Off + add [di],ax + jnc @1 + add word ptr [di+2],1000h +@1: pop ds + end; +end; + +{----------------------------------------------------------------------------} +procedure ConvPtr(p: pointer; var page, off: word); +begin + asm + push ds + lds dx,p + mov bx,ds + mov ax,bx + mov cl,4 + shl ax,cl + add ax,dx + pushf + lds di,off + mov [di],ax + mov ax,bx + mov cl,12 + shr ax,cl + popf + jnc @1 + inc ax +@1: lds di,page + mov [di],ax + pop ds + end; +end; + +{ PRIVATE } + +{----------------------------------------------------------------------------} +procedure fdc_out(value: byte); +var + i: longint; +begin + i:= 128; + while (port[FDC_REG_MSR] and $C0) <> $80 do + begin + dec(i); + if i = 0 then break; + end; + + fdcIOError:= FDC_OK; + if i <> 0 then + port[FDC_REG_DR]:= value + else + fdcIOError:= FDC_ERR_TIMEOUT; +end; + +{----------------------------------------------------------------------------} +function fdc_in: byte; +var + i: longint; +begin + i:= 128; + while (port[FDC_REG_MSR] and $C0) <> $C0 do + begin + dec(i); + if i = 0 then break; + end; + + if i <> 0 then + begin + fdcIOError:= FDC_OK; + fdc_in:= port[FDC_REG_DR] + end + else + begin + fdcIOError:= FDC_ERR_TIMEOUT; + fdc_in:= 0; + end; +end; + +{----------------------------------------------------------------------------} +procedure fdc_wait; +var + WasInt: byte; + Timer: word; +begin + fdcIOError:= FDC_OK; + + WasInt:= 0; + Timer:= 2000; + + while (WasInt = 0) and (Timer > 0) do + begin + dec(Timer); + delay(1); + asm + push DS + push AX + xor AX, AX + mov DS, AX + test byte ptr DS:[43Eh], 80h + jz @noInt + and byte ptr DS:[43Eh], 7Fh + mov WasInt, 1 + @noInt: + pop AX + pop DS + end; + end; + + if WasInt = 0 then + fdcIOError:= FDC_ERR_TIMEOUT; +end; + +{ PUBLIC } + +{----------------------------------------------------------------------------} +procedure fdcMotorOn(drv: byte); +begin + { port[FDC_REG_DOR]:= (drv+1)*16+$C+drv; } + + if drv = 0 then + port[FDC_REG_DOR]:= 28 + else + port[FDC_REG_DOR]:= 45; + + { wait until motor take rpm } + delay(1000);{} +end; + +{----------------------------------------------------------------------------} +procedure fdcMotorOff; +begin + port[FDC_REG_DOR]:= 12; { 12 = $0C = 00001100, bit 3 and 4 } +end; + +{----------------------------------------------------------------------------} +procedure fdcRecalibrate(drv: byte); +begin + fdc_out(FDC_CMD_RECALIBRATE); + fdc_out(drv); + fdc_wait; +end; + +{----------------------------------------------------------------------------} +procedure fdcSeek(drv, trck: byte); +var + a: byte; +begin + fdc_out(FDC_CMD_SEEK); + fdc_out(drv); + fdc_out(trck); + fdc_wait; + + delay(100); +end; + +{----------------------------------------------------------------------------} +procedure fdcSpecify; +var + SRT, HUT, HLT, DMA: byte; +begin +{ +SRT - Step Rate Interval. +Sets the minimum delay between two drive step pulses. +(1-16 ms, SRT = 0Fh corresponds to 1 ms). +Older PC drives did not perform 3- or 4-ms step rates, +and some cannot perform with 2- or even 1-ms step rates. + +HUT - Head Unload Time. +The delay between the completion of a read/write operation and the head lifting. +(16-240 ms, HUT = 0 corresponds to 16 ms). It is usually set to 240 ms. + +HLT - Head Load Time. +The delay between the head load command and the start of a read/write operation. +(2-254 ms, HLT=1-2 ms). Usually set to 2 ms. + +ND - 0: DMA mode. 1: Non-DMA mode. +} + + SRT:= $0F; + HUT:= $0D; + HLT:= $01; + DMA:= $00; + + fdc_out(FDC_CMD_SPECIFY); + fdc_out(SRT or (HUT shl 4)); + fdc_out(DMA or (HLT shl 1)); +end; + +{---------------------------------------------------------------------------} +procedure fdcInit(drv, sector_size_id: byte); +begin + { reset } + port[$3F2]:= 0; + port[$3F2]:= 4; + + fdcMotorOn(drv); + fdcRecalibrate(drv); + fdcRecalibrate(drv); + fdcSeek(drv, 20); + fdcRecalibrate(drv); + fdcSpecify; +end; + +{---------------------------------------------------------------------------} +procedure fdcReadSector(drv, track_id, head_id, sector_id, sector_size_id, last_sector_id: byte); +var + gpl_id: byte; + DMAPage,DMAOfs:word; + BlockSize:word; +begin + { init DMA } + ConvPtr(@fdcBuf, DMAPage, DMAOfs); + BlockSize:= (128 SHL sector_size_id); + asm cli end; + port[$0A]:= $06; { mask channel 2 } + port[$0C]:= $46; { reset trigger } + port[$0B]:= $46; { mode: FDD -> Memory } + port[$04]:= DMAOfs and $FF; + port[$04]:= DMAOfs shr 8; + port[$81]:= DMAPage and $FF; + port[$05]:= (BlockSize-1) and $FF; + port[$05]:= (BlockSize-1) shr 8; + port[$0A]:= $02; { unmask channel 2 } + asm sti end; + + { read data command } + fdc_out(FDC_HCMD_MFM or FDC_CMD_READ_DATA);{} +{ fdc_out( ((head_id and $01) shl 2) or (drv and $03) ); { head (1 bit), drive (2 bits) } + fdc_out(drv); + fdc_out(track_id); + fdc_out(head_id and $01); + fdc_out(sector_id); + fdc_out(sector_size_id); { N: sector size id } + fdc_out(last_sector_id); { EOT: last sector_id on track } + + { GPL values for MFM mode ONLY } + case sector_size_id of + FDC_SECTOR_256: gpl_id:= $0E; + FDC_SECTOR_512: gpl_id:= $1B; + FDC_SECTOR_1024: gpl_id:= $3F; + FDC_SECTOR_2048: gpl_id:= $99; + FDC_SECTOR_4096: gpl_id:= $C8; + FDC_SECTOR_8192: gpl_id:= $C8; { TODO: need to calc it } + else gpl_id:= $2A; { default value } + end; + fdc_out(gpl_id); { GPL: stands for the length of Gap3 } + + { should be FF in MFM mode } + fdc_out($FF); { DTL: if N>0 should be FF and will be ignored } + + fdc_wait; + + fdcStatus[1]:= fdc_in; + fdcStatus[2]:= fdc_in; + fdcStatus[3]:= fdc_in; + fdcStatus[4]:= fdc_in; + fdcStatus[5]:= fdc_in; + fdcStatus[6]:= fdc_in; + fdcStatus[7]:= fdc_in; + + fdc_out(FDC_CMD_GET_STATUS3); + fdc_out(drv); + fdcStatus[8]:= fdc_in; + + { fdcIOError } + fdcIOError:= FDC_OK; + if (fdcStatus[1] and $C0) <> 0 then + begin + fdcIOError:= FDC_ERR_UNKNOWN; + if TestBit(fdcStatus[1],3) then fdcIOError:= FDC_ERR_DRIVE_NOT_READY; + if TestBit(fdcStatus[2],7) then fdcIOError:= FDC_ERR_END_OF_CYLINDER; + if TestBit(fdcStatus[2],5) or TestBit(fdcStatus[3],5) or TestBit(fdcStatus[3],0) then fdcIOError:= FDC_ERR_BAD_SECTOR; + if TestBit(fdcStatus[2],2) or TestBit(fdcStatus[2],4) then fdcIOError:= FDC_ERR_SECTOR_NOT_FOUND; + if TestBit(fdcStatus[2],4) then fdcIOError:= FDC_ERR_DMA_ERROR; + end; + + if (TestBit(fdcStatus[8],1)) then fdcIOError:= FDC_ERR_DRIVE_NOT_READY; +end; + +{----------------------------------------------------------------------------} +function fdcErrorStr(value: byte): string; +begin + fdcErrorStr:= 'Unknown ('+strr(value)+')'; + Case value of + 0: fdcErrorStr:= 'OK'; + 1: fdcErrorStr:= 'Bad Controller'; + 2: fdcErrorStr:= 'Time Out'; + 3: fdcErrorStr:= 'Seek Error'; + 4: fdcErrorStr:= 'Drive Not Ready'; + 5: fdcErrorStr:= 'End Of Cylinder'; + 6: fdcErrorStr:= 'Bad Sector'; + 7: fdcErrorStr:= 'DMA Error'; + 8: fdcErrorStr:= 'Sector Not Found'; + 9: fdcErrorStr:= 'Write Protect'; + 10: fdcErrorStr:= 'Unknown Error'; + 27: fdcErrorStr:= 'User Break'; + End; +end; + +{----------------------------------------------------------------------------} +function fdcSpeedStr(value: byte): string; +begin + fdcSpeedStr:= 'Unexpected format'; + Case value of + 0: fdcSpeedStr:= '500 kb/s (0)'; + 1: fdcSpeedStr:= '300 kb/s (1)'; + 2: fdcSpeedStr:= '250 kb/s (2)'; + 3: fdcSpeedStr:= '125 kb/s (3)'; + End; +end; + +end. diff --git a/HELPERS.PAS b/HELPERS.PAS new file mode 100644 index 0000000..fce5019 --- /dev/null +++ b/HELPERS.PAS @@ -0,0 +1,236 @@ +unit helpers; + +interface + +function strlo(s: string): string; +function mid(str: string; ind1,ind2: integer): string; +function nosp(s: string): string; +function strr(value: longint): string; +function vall(value: string): longint; + +function hob2pc(name: string): string; +function CheckFile(myfile: string): byte; +function GetOf(fullpath: string; what: byte): string; +function CheckEx(myfile: string): string; + +function dec2hex(decn: string): string; + +implementation + +uses + dos; + +{----------------------------------------------------------------------------} +function strlo(s: string): string; +var + f: byte; + a: string; + x: byte; +begin + a:= ''; + for f:= 1 to Length(s) do + begin + x:= 0; + if (((s[f] >= 'A')and(s[f] <= 'Z'))or((s[f] >= '└')and(s[f] <= '╧'))) then x:= 32; + if (s[f] >= '╨')and(s[f] <= '▀') then x:= 80; + a:= a + chr(ord(s[f]) + x); + end; + +strlo:= a; +end; + +{----------------------------------------------------------------------------} +function mid(str: string; ind1,ind2: integer): string; +begin + mid:= Copy(str, ind1, ind2-ind1+1); +end; + +{----------------------------------------------------------------------------} +function nosp(s: string): string; +var + f,l,r: byte; + a: string; +begin + a:= ''; + l:=1; while s[l]=' ' do inc(l); + r:= length(s); while s[r]=' ' do dec(r); + + nosp:= mid(s,l,r); +end; + +{----------------------------------------------------------------------------} +function strr(value: longint): string; +var + r: string; +begin + str(value, r); + + strr:= r; +end; + +{----------------------------------------------------------------------------} +function vall(value: string): longint; +var + rrr: longint; + code: integer; +begin + val(value, rrr, code); + vall:= rrr; +end; + +{----------------------------------------------------------------------------} +function hob2pc(name: string): string; +var + i, m: byte; + s, d: string; +begin + s:= nosp(mid(name,1,8)); + d:= copy(strlo(s), 1, 3); + if (d='com') or (d='lpt') or (d='nul') or (d='con') or (d='aux') or (d='prn') then s:= s + d; + + for i:= 1 to length(s) do + begin + if s[i] = ' ' then s[i]:= '_'; + if s[i] in ['.',':',',','\','/','?','*','>','<','+','"',#39] then s[i]:= '-'; + if s[i] = #0 then s[i]:= '0'; + if s[i] = #1 then s[i]:= '1'; + if s[i] = #2 then s[i]:= '2'; + if s[i] = #3 then s[i]:= '3'; + if s[i] = #4 then s[i]:= '4'; + if s[i] = #5 then s[i]:= '5'; + if s[i] = #6 then s[i]:= '6'; + if s[i] = #7 then s[i]:= '7'; + if s[i] = #8 then s[i]:= '8'; + if s[i] = #9 then s[i]:= '9'; + if s[i] = #10 then s[i]:= 'A'; + if s[i] = #11 then s[i]:= 'B'; + if s[i] = #12 then s[i]:= 'C'; + if s[i] = #13 then s[i]:= 'D'; + if s[i] = #14 then s[i]:= 'E'; + if s[i] = #15 then s[i]:= 'F'; + if s[i] = #16 then s[i]:= 'G'; + if s[i] = #17 then s[i]:= 'H'; + if s[i] = #18 then s[i]:= 'I'; + if s[i] = #19 then s[i]:= 'J'; + if s[i] = #20 then s[i]:= 'K'; + if s[i] = #21 then s[i]:= 'L'; + if s[i] = #22 then s[i]:= 'M'; + if s[i] = #23 then s[i]:= 'N'; + if s[i] = #24 then s[i]:= 'O'; + if s[i] = #25 then s[i]:= 'P'; + if s[i] = #26 then s[i]:= 'Q'; + if s[i] = #27 then s[i]:= 'R'; + if s[i] = #28 then s[i]:= 'S'; + if s[i] = #29 then s[i]:= 'T'; + if s[i] = #30 then s[i]:= 'U'; + if s[i] = #31 then s[i]:= 'V'; + end; + + hob2pc:= s; +end; + +{----------------------------------------------------------------------------} +{$I-} +function CheckFile(myfile: string): byte; +var + ff: searchrec; +begin + filemode:= 0; + findfirst(myfile, anyfile, ff); + CheckFile:= doserror; +end; +{$I+} + +{----------------------------------------------------------------------------} +function GetOf(fullpath: string; what: byte): string; +var + dosdir :dirstr; + dosname :namestr; + dosext :extstr; +begin + FSplit(fullpath, dosdir, dosname, dosext); + if length(dosdir) <> 3 then dosdir := Copy(dosdir, 1, Length(dosdir)-1); + case what of + 1: GetOf := dosdir; + 2: GetOf := dosname; + 3: GetOf := dosext; + end; +end; + +{----------------------------------------------------------------------------} +function CheckEx(myfile: string): string; +var + e: byte; + s,t,fn,ex: string; + i: longint; +begin + CheckEx:= myfile; + + {file exists} + e:= CheckFile(myfile); + if e <> 0 then + exit; + + fn:= GetOf(myfile,2); + ex:= GetOf(myfile,3); + + i:= 0; + while (e = 0) do + begin + inc(i); + t:= strr(i); + s:= copy(fn,1,5); + s:= s + copy('00000000', 1, 8-length(s)-length(t)) + t; + + e:= CheckFile(s+ex); + end; + + CheckEx:= s+ex; +end; + +{----------------------------------------------------------------------------} +function dec2hex(decn: string): string; +var + hex: string; + f, tdec, valcode, h3, h4: integer; + decm: array [1..2] of real; + i: longint; +label + fin; +begin + hex:= ''; + Val(decn, tdec, valcode); + if (tdec < 0) or (tdec > 65535) then + begin + hex:= 'error'; + goto fin; + end; + decm[1]:= int(tdec / 256); + decm[2]:= tdec - 256 * decm[1]; + for i:= 1 to 2 do + begin + h3:= 48; + h4:= 48; + for f:= 1 to round(decm[i]) do + begin + h4:= h4 + 1; + if (h4 > 57) and (h4 < 65) then + h4:= h4 + 7; + if h4 > 70 then + begin + h3:= h3 + 1; + h4:= 48; + end; + if (h3 > 57) and (h3 < 65) then + h3:= h3 + 7; + end; + hex:= hex + chr(h3) + chr(h4); + end; +fin: + if vall(decn) > 255 then + dec2hex:= hex + else + dec2hex:= copy(hex, 3, 2); +end; + +end. \ No newline at end of file diff --git a/LD-ISDOS.PAS b/LD-ISDOS.PAS new file mode 100644 index 0000000..8a006e7 --- /dev/null +++ b/LD-ISDOS.PAS @@ -0,0 +1,354 @@ +uses + dos, crt, + helpers, + fdc; + +const + SEP = '--------------------------------------------------------------------------'; + +var + tmp: TFDCBbuffer; + drive: byte; + i: integer; + startTrack, maxTrack: byte; + ff: file; + tries, track, head, sector, sc: byte; + out_file_name, d: string; + fdcIOErrorBackup: byte; + maxTries: byte; + testMode, motorOffMethod, showDump: boolean; + c: char; + showDumpSector: byte; + +{----------------------------------------------------------------------------} +function fdcGetSpeed(drv: byte): byte; +var + speed_id: byte; +begin + fdcGetSpeed:= 255; { speed unknown } + + for speed_id:= 0 to FDC_SPEED_COUNT do + begin + port[FDC_REG_DIR]:= speed_id; + + fdcReadSector(drv,0,0,1,FDC_SECTOR_1024,9); { ISDOS specific } + if fdcIOError = FDC_OK then + begin + fdcGetSpeed:= speed_id; + exit; + end; + end; + + fdcIOError:= FDC_ERR_SECTOR_NOT_FOUND; +end; + +{----------------------------------------------------------------------------} +function GetMaxTrack(param: string): byte; +begin + GetMaxTrack:= 79; + + if param[3] = '1' then GetMaxTrack:= 80; + if param[3] = '2' then GetMaxTrack:= 81; + if param[3] = '3' then GetMaxTrack:= 82; + if param[3] = '4' then GetMaxTrack:= 83; + if param[3] = '5' then GetMaxTrack:= 84; + + if length(param) = 2 then GetMaxTrack:= 82; +end; + +{----------------------------------------------------------------------------} +function GetMaxTries(param: string): byte; +begin + GetMaxTries:= 3; + + if param[3] = '4' then GetMaxTries:= 4; + if param[3] = '5' then GetMaxTries:= 5; + if param[3] = '6' then GetMaxTries:= 6; + if param[3] = '7' then GetMaxTries:= 7; + if param[3] = '8' then GetMaxTries:= 8; + if param[3] = '9' then GetMaxTries:= 9; +end; + +{----------------------------------------------------------------------------} +begin + ClrScr; + + drive:= 0; + startTrack:= 0; + maxTrack:= 79; + out_file_name:= '_isdos.isd'; + maxTries:= 5; + testMode:= false; + motorOffMethod:= false; + showDump:= false; + showDumpSector:= 1; + +{----------------------------------------------------------------------------} + if ParamCount = 1 then + begin + d:= strlo(ParamStr(1)); + + { drive } + if d = 'a:' then drive:= 0; + if d = 'b:' then drive:= 1; + end; + + if ParamCount > 1 then + begin + d:= strlo(ParamStr(1)); + + { drive } + if d = 'a:' then drive:= 0; + if d = 'b:' then drive:= 1; + + d:= strlo(ParamStr(2)); + + { out file name} + if d[1] <> '/' then out_file_name:= d; + end; + + for i:= 1 to ParamCount do + begin + d:= strlo(ParamStr(i)); + if copy(d,1,2) = '/t' then + begin + testMode:= true; + startTrack:= 80; + maxTrack:= GetMaxTrack(d); + continue; + end; + if copy(d,1,2) = '/m' then + begin + maxTrack:= GetMaxTrack(d); + continue; + end; + if copy(d,1,2) = '/r' then + begin + maxTries:= GetMaxTries(d); + continue; + end; + if copy(d,1,2) = '/o' then + begin + motorOffMethod:= true; + continue; + end; + if copy(d,1,2) = '/d' then + begin + showDump:= true; + if (length(d) = 3) and (d[3] = '1') then showDumpSector:= 1; + if (length(d) = 3) and (d[3] = '2') then showDumpSector:= 2; + if (length(d) = 3) and (d[3] = '3') then showDumpSector:= 3; + if (length(d) = 3) and (d[3] = '4') then showDumpSector:= 4; + if (length(d) = 3) and (d[3] = '5') then showDumpSector:= 5; + if (length(d) = 3) and (d[3] = '6') then showDumpSector:= 6; + if (length(d) = 3) and (d[3] = '7') then showDumpSector:= 7; + if (length(d) = 3) and (d[3] = '8') then showDumpSector:= 8; + if (length(d) = 3) and (d[3] = '9') then showDumpSector:= 9; + continue; + end; + end; + +{----------------------------------------------------------------------------} + writeln('ZX Spectrum Navigator v1.15 Reading iS-DOS floppy disk'); + writeln('https://zxsn.ru, RomanRom2@gmail.com'); + writeln('Copyright (c) 1996-2026 RomanRom2'); + writeln(SEP); + + if strlo(ParamStr(1)) = '/h' then + begin + writeln('LD-ISDOS.EXE drive|key '); + writeln(' - key /dN try to show dump of track 0 head 0 sector N'); + writeln(' by default N=1, means /d is the same /d1'); + writeln(' - key /o enable MotorOff method each 4,6,8 tries'); + writeln(' - key /rN set max tries to read bad sector'); + writeln(' by default N=5'); + writeln(' - key /mN enable 8N tracks, N = 1..5 means 81-85 tracks'); + writeln(' /m is the same /m3 for 83'); + writeln('by default drive [A:], file name gets from disk name'); + writeln(SEP); + writeln('Examples:'); + writeln('LD-ISDOS.EXE /m5 - dump disk A: names as DiskName with max tracks'); + writeln('LD-ISDOS.EXE b: - dump disk B: names as DiskName'); + writeln('LD-ISDOS.EXE a: MYDSK - dump disk A: names as MYDSK'); + writeln('LD-ISDOS.EXE a: MYDSK /m2 - dump disk A: names as MYDSK with 82 tracks'); + writeln('LD-ISDOS.EXE a: /d9 - dump disk A: names as DiskName with dump sector 9'); + writeln('LD-ISDOS.EXE /d /r2 - dump disk A: names as DiskName with dump sector 1'); + writeln(' and 2 retries to read bad sectors'); + end + else + begin + writeln('LD-ISDOS.EXE /h - for help'); + end; + writeln(SEP); + + writeln; + if strlo(ParamStr(1)) = '/h' then exit; + +{----------------------------------------------------------------------------} + + writeln('Drive ',chr(drive+65),': is initializing...'); + + fdcInit(drive, FDC_SECTOR_1024); + if fdcIOError <> FDC_OK then + begin + writeln('FDC init error ['+fdcErrorStr(fdcIOError)+']'); + fdcRecalibrate(drive); + fdcMotorOff; + exit; + end; + + writeln(fdcErrorStr(fdcIOError),', ',fdcSpeedStr(fdcGetSpeed(drive)));{} + + { do not show it in test mode } + if not testMode then + begin + { check 1st sector for disk name } + fdcReadSector(drive,0,0,1,FDC_SECTOR_1024,9); + if fdcIOError <> FDC_OK then + begin + writeln('1st sector read error ['+fdcErrorStr(fdcIOError)+']'); + fdcRecalibrate(drive); + fdcMotorOff; + exit; + end; + + { get disk name } + d:=''; for i:=1 to 8 do if fdcBuf[i+2]<>32 then d:=d+chr(fdcBuf[i+2]); + if out_file_name = '_isdos.isd' then out_file_name:= hob2pc(d)+'.isd';; + write('Disk name: [',d,']'); + + out_file_name:= CheckEx(out_file_name); + writeln(' (',out_file_name,')'); + + if motorOffMethod then writeln('MotorOff method each 4,6,8 tries is enabled'); + + if showDump then + begin + { dump 1st sector } + fdcReadSector(drive,0,0,showDumpSector,FDC_SECTOR_1024,9); + writeln(SEP); + for i:= 0 to 15 do + begin + for track:= 0 to 15 do + begin + gotoxy((track+1)*3,wherey); write(dec2hex(strr(fdcBuf[1+i*16+track]))); + gotoxy(51+(track+1),wherey); + if fdcBuf[1+i*16+track]>31 then write(chr(fdcBuf[1+i*16+track])) else write('.'); + end; + writeln; + end; + + writeln(SEP); + writeln('ESC - cancel, any key - continue'); + + c:= readkey; + if c = #27 then + begin + writeln; + writeln('Canceled.'); + fdcRecalibrate(drive); + fdcMotorOff; + exit; + end; + end; + + writeln; + writeln('Dumping ',maxTrack+1,' tracks...'); + end + else + begin + writeln; + writeln('TEST [',startTrack,'..',maxTrack+1,'] TRACKS MODE'); + end; + + +{----------------------------------------------------------------------------} + if not testMode then + begin + { do not dump in test mode } + assign(ff, out_file_name); + rewrite(ff, 1); + end; + + + for track:= startTrack to maxTrack do + begin + fdcSeek(drive, track); + + for head:= 0 to 1 do + Begin + for i:=1 to 5*1024 do tmp[i]:= 0; { empty buffer by zero } + + for sector:= 1 to 5 do + begin + if keypressed then break; + + sc:= sector; + if sector = 5 then sc:= 9; + + write('Track:',track:2,' Head:',head:1,' Sector:',sc,' '); + + { mark sector as a bad sector } + for i:=1 to 1024 do tmp[(sector-1)*1024+i]:= ord('B'); + + for tries:= 1 to maxTries do + begin + if keypressed then break; + + fdcReadSector(drive+(head shl 2),track,head,sc,FDC_SECTOR_1024,9); + fdcIOErrorBackup:= fdcIOError; + + if fdcIOErrorBackup = FDC_OK then break; + + write('.'); + + if motorOffMethod then + begin + if tries in [4,6,8] then + begin + fdcMotorOff; + delay(100); + fdcMotorOn(drive); + continue; + end; + end; + + if track > 4 then fdcSeek(drive, track-4) else fdcSeek(drive, 0); + fdcSeek(drive,track); + end; + + if fdcIOErrorBackup = FDC_ERR_BAD_SECTOR then + write(fdcErrorStr(fdcIOErrorBackup)+' (saved) '+#13) + else + write(fdcErrorStr(fdcIOErrorBackup)+' '+#13); + + if fdcIOErrorBackup <> FDC_OK then writeln; + + { save buffer only if [OK] or [BAD_SECTOR] } + if fdcIOErrorBackup in [FDC_OK, FDC_ERR_BAD_SECTOR] then + for i:=1 to 1024 do tmp[(sector-1)*1024+i]:= fdcBuf[i]; + end; + + { do not dump in test mode } + if not testMode then + BlockWrite(ff, tmp, 5*1024); { dump full track } + End; + + if KeyPressed then + if ReadKey = #27 then + begin + writeln(#13#10'... break pressed'); + break; + end; + end; + + { do not dump in test mode } + if not testMode then + close(ff); + + fdcRecalibrate(drive); + fdcMotorOff; + + write(#13' '); + writeln(#13#10'Done.'#13#10); +end. diff --git a/LD-TRDOS.PAS b/LD-TRDOS.PAS new file mode 100644 index 0000000..e3ed364 --- /dev/null +++ b/LD-TRDOS.PAS @@ -0,0 +1,363 @@ +uses + dos, crt, + helpers, + fdc; + +const + SEP = '--------------------------------------------------------------------------'; + +var + tmp: TFDCBbuffer; + drive: byte; + i: integer; + startTrack, maxTrack: byte; + ff: file; + tries, track, head, sector: byte; + out_file_name, d: string; + fdcIOErrorBackup: byte; + HOBETA: boolean; + maxTries: byte; + testMode, motorOffMethod, showDump: boolean; + c: char; + showDumpSector: byte; + +{----------------------------------------------------------------------------} +function fdcGetSpeed(drv: byte): byte; +var + speed_id: byte; +begin + fdcGetSpeed:= 255; { speed unknown } + + for speed_id:= 0 to FDC_SPEED_COUNT do + begin + port[FDC_REG_DIR]:= speed_id; + + fdcReadSector(drv,0,0,9,FDC_SECTOR_256,16); { TRDOS specific } + if fdcIOError = FDC_OK then + begin + fdcGetSpeed:= speed_id; + exit; + end; + end; + + fdcIOError:= FDC_ERR_SECTOR_NOT_FOUND; +end; + +{----------------------------------------------------------------------------} +function GetMaxTrack(param: string): byte; +begin + GetMaxTrack:= 79; + + if param[3] = '1' then GetMaxTrack:= 80; + if param[3] = '2' then GetMaxTrack:= 81; + if param[3] = '3' then GetMaxTrack:= 82; + if param[3] = '4' then GetMaxTrack:= 83; + if param[3] = '5' then GetMaxTrack:= 84; + if param[3] = '6' then GetMaxTrack:= 85; { extra } + if param[3] = '7' then GetMaxTrack:= 86; { extra } + + if length(param) = 2 then GetMaxTrack:= 84; +end; + +{----------------------------------------------------------------------------} +function GetMaxTries(param: string): byte; +begin + GetMaxTries:= 3; + + if param[3] = '4' then GetMaxTries:= 4; + if param[3] = '5' then GetMaxTries:= 5; + if param[3] = '6' then GetMaxTries:= 6; + if param[3] = '7' then GetMaxTries:= 7; + if param[3] = '8' then GetMaxTries:= 8; + if param[3] = '9' then GetMaxTries:= 9; +end; + +{----------------------------------------------------------------------------} +begin + ClrScr; + + drive:= 0; + startTrack:= 0; + maxTrack:= 79; + out_file_name:= '_trdos.trd'; + HOBETA:= false; + maxTries:= 5; + testMode:= false; + motorOffMethod:= false; + showDump:= false; + showDumpSector:= 1; + +{----------------------------------------------------------------------------} + if ParamCount = 1 then + begin + d:= strlo(ParamStr(1)); + + { drive } + if d = 'a:' then drive:= 0; + if d = 'b:' then drive:= 1; + end; + + if ParamCount > 1 then + begin + d:= strlo(ParamStr(1)); + + { drive } + if d = 'a:' then drive:= 0; + if d = 'b:' then drive:= 1; + + d:= strlo(ParamStr(2)); + + { out file name} + if d[1] <> '/' then out_file_name:= d; + end; + + for i:= 1 to ParamCount do + begin + d:= strlo(ParamStr(i)); + if copy(d,1,2) = '/t' then + begin + testMode:= true; + startTrack:= 80; + maxTrack:= GetMaxTrack(d); + continue; + end; + if copy(d,1,2) = '/m' then + begin + maxTrack:= GetMaxTrack(d); + continue; + end; + if copy(d,1,2) = '/r' then + begin + maxTries:= GetMaxTries(d); + continue; + end; + if copy(d,1,2) = '/o' then + begin + motorOffMethod:= true; + continue; + end; + if copy(d,1,2) = '/d' then + begin + showDump:= true; + if (length(d) = 3) and (d[3] = '1') then showDumpSector:= 1; + if (length(d) = 3) and (d[3] = '2') then showDumpSector:= 2; + if (length(d) = 3) and (d[3] = '3') then showDumpSector:= 3; + if (length(d) = 3) and (d[3] = '4') then showDumpSector:= 4; + if (length(d) = 3) and (d[3] = '5') then showDumpSector:= 5; + if (length(d) = 3) and (d[3] = '6') then showDumpSector:= 6; + if (length(d) = 3) and (d[3] = '7') then showDumpSector:= 7; + if (length(d) = 3) and (d[3] = '8') then showDumpSector:= 8; + if (length(d) = 3) and (d[3] = '9') then showDumpSector:= 9; + continue; + end; + end; + +{----------------------------------------------------------------------------} + writeln('ZX Spectrum Navigator v1.15 Reading TR-DOS floppy disk'); + writeln('https://zxsn.ru, RomanRom2@gmail.com'); + writeln('Copyright (c) 1996-2026 RomanRom2'); + writeln(SEP); + + if strlo(ParamStr(1)) = '/h' then + begin + writeln('LD-TRDOS.EXE drive|key '); + writeln(' - key /dN try to show dump of track 0 head 0 sector N'); + writeln(' by default N=1, means /d is the same /d1'); + writeln(' - key /o enable MotorOff method each 4,6,8 tries'); + writeln(' - key /rN set max tries to read bad sector'); + writeln(' by default N=5'); + writeln(' - key /mN enable 8N tracks, N = 1..5 means 81-85 tracks'); + writeln(' /m is the same /m3 for 83'); + writeln('by default drive [A:], file name gets from disk name'); + writeln(SEP); + writeln('Examples:'); + writeln('LD-TRDOS.EXE /m5 - dump disk A: names as DiskName with max tracks'); + writeln('LD-TRDOS.EXE b: - dump disk B: names as DiskName'); + writeln('LD-TRDOS.EXE a: MYDSK - dump disk A: names as MYDSK'); + writeln('LD-TRDOS.EXE a: MYDSK /m2 - dump disk A: names as MYDSK with 82 tracks'); + writeln('LD-TRDOS.EXE a: /d9 - dump disk A: names as DiskName with dump sector 9'); + writeln('LD-TRDOS.EXE /d /r2 - dump disk A: names as DiskName with dump sector 1'); + writeln(' and 2 retries to read bad sectors'); + end + else + begin + writeln('LD-TRDOS.EXE /h - for help'); + end; + writeln(SEP); + + writeln; + if strlo(ParamStr(1)) = '/h' then exit; + +{----------------------------------------------------------------------------} + writeln('Drive ',chr(drive+65),': is initializing...'); + + fdcInit(drive, FDC_SECTOR_256); + if fdcIOError <> FDC_OK then + begin + writeln('FDC init error ['+fdcErrorStr(fdcIOError)+']'); + fdcMotorOff; + exit; + end; + + writeln(fdcErrorStr(fdcIOError),', ',fdcSpeedStr(fdcGetSpeed(drive))); + + { check hobeta style format (HEAD ID always = 0) } + fdcReadSector(drive+(1 shl 2),0,1,9,FDC_SECTOR_256,16); + if fdcIOError <> FDC_OK then + begin + writeln('HOBETA or real TR-DOS formatted'); + HOBETA:= true; + end; + + { do not show it in test mode } + if not testMode then + begin + { check 9th system sector for disk name } + fdcReadSector(drive,0,0,9,FDC_SECTOR_256,16); + if fdcIOError <> FDC_OK then + begin + writeln('9th sector read error ['+fdcErrorStr(fdcIOError)+']'); + fdcRecalibrate(drive); + fdcMotorOff; + exit; + end; + + { get disk name } + d:=''; for i:=1 to 8 do if fdcBuf[$F5+i]<>32 then d:=d+chr(fdcBuf[$F5+i]); + if out_file_name = '_trdos.trd' then out_file_name:= hob2pc(d)+'.trd';; + write('Disk name: [',d,']'); + + out_file_name:= CheckEx(out_file_name); + writeln(' (',out_file_name,')'); + + if motorOffMethod then writeln('Motor off method each 4,6,8 tries is enabled'); + + if showDump then + begin + { dump 1st sector } + fdcReadSector(drive,0,0,showDumpSector,FDC_SECTOR_256,16); + writeln(SEP); + for i:= 0 to 15 do + begin + for track:= 0 to 15 do + begin + gotoxy((track+1)*3,wherey); write(dec2hex(strr(fdcBuf[1+i*16+track]))); + gotoxy(51+(track+1),wherey); + if fdcBuf[1+i*16+track]>31 then write(chr(fdcBuf[1+i*16+track])) else write('.'); + end; + writeln; + end; + + writeln(SEP); + writeln('ESC - cancel, any key - continue'); + + c:= readkey; + if c = #27 then + begin + writeln; + writeln('Canceled.'); + fdcRecalibrate(drive); + fdcMotorOff; + exit; + end; + end; + + writeln; + writeln('Dumping ',maxTrack+1,' tracks...'); + end + else + begin + writeln; + writeln('TEST [',startTrack,'..',maxTrack+1,'] TRACKS MODE'); + end; + +{----------------------------------------------------------------------------} + if not testMode then + begin + { do not dump in test mode } + assign(ff, out_file_name); + rewrite(ff, 1); + end; + + for track:= startTrack to maxTrack do + begin + fdcSeek(drive, track); + + for head:= 0 to 1 do + Begin + for i:= 1 to 16*256 do tmp[i]:= 0; { empty buffer by zero} + + for sector:= 1 to 16 do + begin + if keypressed then break; + + write('Track:',track:2,' Head:',head:1,' Sector:',sector:2,' '); + + { mark sector as a bad sector } + for i:=1 to 256 do tmp[(sector-1)*256+i]:= ord('B'); + + for tries:= 1 to maxTries do + begin + if keypressed then break; + + i:= head; + if HOBETA then i:= 0; + + fdcReadSector(drive+(head shl 2),track,i,sector,FDC_SECTOR_256,16); + fdcIOErrorBackup:= fdcIOError; + + if fdcIOErrorBackup = FDC_OK then + break; + + write('.'); + + if motorOffMethod then + begin + if tries in [4,6,8] then + begin + fdcMotorOff; + delay(100); + fdcMotorOn(drive); + continue; + end; + end; + + if track > 4 then fdcSeek(drive, track-4) else fdcSeek(drive, 0); + fdcSeek(drive, track); + end; + + if fdcIOErrorBackup = FDC_ERR_BAD_SECTOR then + write(fdcErrorStr(fdcIOErrorBackup)+' (saved) '+#13) + else + write(fdcErrorStr(fdcIOErrorBackup)+' '+#13); + + if fdcIOErrorBackup <> FDC_OK then writeln; + + { save buffer only if [OK] or [BAD_SECTOR] } + if fdcIOErrorBackup in [FDC_OK, FDC_ERR_BAD_SECTOR] then + for i:=1 to 256 do tmp[(sector-1)*256+i]:= fdcBuf[i]; + end; + + { do not dump in test mode } + if not testMode then + BlockWrite(ff, tmp, 16*256); { dump full track } + End; + + if KeyPressed then + if ReadKey = #27 then + begin + writeln(#13#10'... break pressed'); + break; + end; + end; + + { do not dump in test mode } + if not testMode then + close(ff); + + fdcRecalibrate(drive); + fdcMotorOff; + + write(#13' '); + writeln(#13#10'Done.'#13#10); +end. diff --git a/docs/8272.txt b/docs/8272.txt new file mode 100644 index 0000000..9ffe92f --- /dev/null +++ b/docs/8272.txt @@ -0,0 +1,486 @@ + Контроллер НГМД i8272. ╔═════╦╗ + Описание работы контроллера и системы команд. ║i8272║║ + ╚═════╩╝ + Для доступа со стороны процессора контроллер 8272 имеет 2 регистра: +регистр состояния и регистр данных. Регистр состояния (Main Status Register) +содержит информацию о состоянии контроллера и может быть считан процессором в +любое время. Через регистр данных контроллера осуществляется доступ ко всем +внутренним регистрам 8272, в него записываются команды и осуществляется обмен +данными с диском. Регистр состояния можно только считывать. Для выбора одного +из двух регистров используется вывод А0 8272 (выв.5). При А0=0 адресуется +регистр состояния, при А0=1 адресуется регистр данных. + + Формат регистра состояния: + ╔═════╦═════╦═════╦═════╦═════╦═════╦═════╦═════╗ + ║ RQM ║ DIO ║ NDM ║ CB ║ D3B ║ D2B ║ D1B ║ D0B ║ + ╠═════╬═════╬═════╬═════╬═════╬═════╬═════╬═════╣ + ║ DB7 ║ DB6 ║ DB5 ║ DB4 ║ DB3 ║ DB2 ║ DB1 ║ DB0 ║ + ╚═════╩═════╩═════╩═════╩═════╩═════╩═════╩═════╝ + + Описание разрядов регистра состояния: + + RQM - Request For Master + информирует процессор о готовности к обмену данными по шине данных. + RQM = 1 - контроллер к обмену готов. + DIO - Data Input/Output + информирует процессор об ожидаемом направлении пересылки данных: + DIO = 1 - направление пересылки - в процессор (Read), + DIO = 0 - направление пересылки - из процессора (Write). + NDM - Non DMA Mode + В режиме НЕ-ПДП бит NDM = 0 показывает, что закончена фаза исполнения + команды. + CB - FDC Busy + Если бит CB = 1, это означает, что контроллер в данный момент занят - + выполняется операция чтения/записи. + DB3..DB0 - Drive n Busy + Эти биты показывают состояние каждого из 4-х накопителей. Если + содержимое бита = 1, значит для соответствующего накопителя в + настоящее время выполняется команда Seek. + + Общее описание контроллера. + ──────────────────────────── + В систему команд контроллера 8272 входит 15 команд. Каждая команда +идентифицируется многобайтной пересылкой по шине данных в регистр данных +контроллера. Результат выполнения команды также может быть многобайтным. +Каждую команду удобно представлять состоящей из 3-х фаз: + * Фаза приказа - контроллер принимает от процессора последовательность + байт, необходимых для выполнения команды. + * Фаза исполнения - контроллер выполняет переданную ему команду. + * Фаза результата - процессор считывает состояние контроллера после + выполнения команды и другую информацию. + + На фазах приказа и результата перед передачей каждого байта из/в регистр +данных контроллера, процессор должен считывать содержимое регистра состояния +контроллера. Биты RQM и DIO регистра состояния должны быть установлены в 1 и +0 соответственно перед тем, как очередной байт будет передан в контроллер. +Многие команды являются многобайтовыми, поэтому для них необходимо считывать +и проверять регистр состояния перед пересылкой каждого байта в контроллер. На +фазе результата биты RQM и DIO должны быть установлены в 1 перед чтением +каждого байта из контроллера. Отметим, что чтение регистра состояния перед +пересылкой каждого байта необходимо только на фазах приказа и результата. + На фазе исполнения регистр состояния считывать не нужно. Если контроллер +находится в режиме NON DMA (НЕ-ПДП), появление очередного байта данных при +чтении с диска сопровождается появлением сигнала прерывания INT=1. При +появлении сигнала чтения (RD=0), сигнал прерывания сбрасывается и данные +выдаются на шину данных. Например, если процессор не может обслуживать +прерывания достаточно быстро (каждые 13 мксек. при двойной плотности), он +может опрашивать регистр состояния и бит D7 (RQM) соответствует сигналу +прерывания. При выполнении команды записи аналогично сигнал записи WR=0 +сбрасывает прерывание. + Если контроллер находится в режиме DMA (ПДП), то прерывание на фазе +исполнения не генерируется. Контроллер в этом случае выдает сигнал DRQ +(запрос ПДП) когда появляется очередной байт данных. Контроллер ПДП отвечает +на этот запрос сигналом подтверждения ПДП DACK=0 и RD=0. При появлении +сигнала DACK сбрасывается сигнал DRQ. При выполнении операции записи вместо +сигнала RD генерируется сигнал WR=0. + По окончании фазы исполнения (при появлении сигнала ТС - конец счета) +генерируется прерывание, означающее начало фазы результата. При чтении +первого байта результата сигнал прерывания сбрасывается. + Необходимо подчеркнуть, что на фазе результата все байты, указанные в +таблице команд, должны быть считаны процессором. Например, команда чтения +данных имеет 7 байт результата и все 7 байт должны быть считаны в порядке, +указанном в таблице команд, для успешного завершения операции. Контроллер не +воспримет следующую команду до тех пор, пока не будут считаны все 7 байт +результата после выполнения команды чтения. + Контроллер 8272 содержит 5 регистров состояния: главный регистр +состояния (Main Status Register) и регистры ST0-ST3. Главный регистр +состояния (или просто регистр состояния) может быть считан процессором в +любое время. Регистры ST0-ST3 доступны процессору только на фазе результата и +могут быть считаны им после завершения некоторой команды. Конкретная команда +определяет, сколько и какие регистры могут и должны быть считаны. + Байты данных, записываемые в контроллер на фазе приказа и считываемые из +него на фазе результата, должны следовать в порядке, указанном в таблице +команд. Изменение этих последовательностей не допускается. После получения +последнего байта команды контроллер автоматически начинает выполнять команду, +переходя к фазе исполнения. После того, как на фазе результата считывается +последний байт, контроллер считает эту команду завершенной и готов к +обработке следующей команды. Команда может быть прекращена только подачей +сигнала конца счета ТС=1. Это удобное средство для "привлечения внимания" +контроллера в критических ситуациях. + После передачи в контроллер команды Specify, шины выбора накопителя +начинают автоматически сканироваться в промежутках между командами (а также +между импульсами шага в команде Seek). Контроллер опрашивает состояние +сигнала готовности Ready всех 4-х накопителей. Если сигнал Ready изменяет +свое состояние (обычно из-за открытия дверки накопителя), контроллер +генерирует прерывание. Процессор передачей команды Sense Interrupt Status +считывает содержимое регистра ST0 и по биту NR (Not Ready) регистра ST0 +определяет состояние накопителя. + + Описание команд 8272. + ─────────────────────── + На фазе приказа перед вводом каждого байта должен опрашиваться регистр +состояния 8272. При этом биты DIO (D6) и RQM (D7) должны иметь значения 0 и 1 +соответственно перед записью каждого байта команды в контроллер. Начало фазы +выполнения вызывает установку этих битов в 1 и 0 соответственно. + + Read Data Чтение данных + ═════════ ═════════════ + Для задания этой команды в контроллер передается последовательность из 9 +байт (см. таблицу команд). После получения этой последовательности контроллер +выдает сигнал подвода головки к поверхности диска (если она отведена), +отрабатывает паузу для подвода головки (заданную в команде Specify) и +начинает поиск адресной метки сектора, после чего считывает поле +идентификатора сектора. Когда текущий номер сектора ("R"), хранящийся в +регистре IDR совпадает с номером сектора, считанного с диска, контроллер +начинает вводить данные из поля данных сектора и последовательно, байт за +байтом, выдавать их на шину данных. + После окончания чтения сектора контроллер инкрементирует на 1 номер +сектора и начинает считывать данные из следующего сектора. Такой обмен носит +название мультисекторного. Выполнение команды может быть прекращено подачей +сигнала TC (Terminal Count - конец счета). После принятия сигнала ТС +контроллер прекращает передачи по шине данных, однако продолжает читать +данные текущего сектора вплоть до байтов CRC-контроля, после чего операция +прекращается. + Количество байт, подлежащих считыванию, зависит от значений битов MT, +MFM и N, заданных в команде. + Бит МТ задает многодорожечный (multitrack) режим контроллера, +позволяющий ему считывать данные с обеих сторон (дорожек) диска. В этом +случае для указанного цилиндра будут переданы все сектора, начиная с сектора +1 стороны 0 и заканчивая последним сектором стороны 1. Заметим, что этот +режим относится только к одному цилиндру. + В случае N=0 значение DTL определяет количество данных, которые +контроллер должен трактовать как один сектор. Если DTL меньше истинного +размера сектора, то данные из сектора после передачи DTL байт не передаются +на шину данных. Контроллер же считывает сектор полностью, вплоть до байтов +CRCконтроля и, если это задано в команде, может продолжить мультисекторное +чтение. Если N > 0, то значение DTL игнорируется и устанавливается в 0FFH. + После завершения чтения контроллер не отводит головку накопителя от +поверхности диска до истечения интервала времени, указанного в команде +Specify. Поэтому между двумя последовательными частыми обращениями головка +остается прижатой к поверхности диска. + Если контроллер второй раз обнаруживает индексный импульс, не обнаружив +правильного номера сектора (заданного R), он устанавливает флаг ND (No Data) +в регистре ST1 и заканчивает выполнение команды (в регистре ST0 также +устанавливаются биты D7 и D6 в 0 и 1 соответственно). + После чтения поля идентификатора и поля данных каждого сектора, +контроллер производит CRC-контроль считанных байтов. Если обнаружена ошибка +CRC в поле идентификатора сектора, контроллер устанавливает флаг DE (Data +Error) в регистре ST1, если же ошибка обнаружена в поле данных сектора, +контроллер устанавливает флаг DD (Data error in Data field) в регистре ST1. В +обоих случаях устанавливаются биты D7 и D6 в регистре ST0 в 0 и 1 +соответственно, и выполнение команды завершается. + Если контроллер встречает адресный маркер удаленных данных и если бит SK +(Skip - бит D5 в команде) не установлен, то контроллер устанавливает флаг CM +(Control Mark) в регистре ST2 и заканчивает операцию после чтения всех данных +сектора. Если же бит SK=1, контроллер пропускает этот сектор и начинает +считывать следующий. + Во время передачи данных процессор должен обслуживать контроллер не реже +1 раза в 27 мксек. при одинарной плотности и 13 мксек. - при двойной. В +противном случае контроллер устанавливает флаг OR (Over Run) в регистре ST1 и +заканчивает операцию. + После завершения операции чтения (это также относится и к команде записи +данных) информация, считываемая из контроллера на фазе результата (байты +C-H-R-H) зависит от значения битов МТ и байта ЕОТ команды. + + + Write Data Запись данных + ══════════ ═════════════ + Для задания этой команды в контроллер передается последовательность +из 9 байт (см. таблицу команд). После получения последнего байта команды +контроллер выдает сигнал подвода головки к поверхности диска (если она была +отведена) и отрабатывает задержку для подвода головки, заданную в команде +Specify и начинает поиск поля идентификатора сектора. Если текущий номер +сектора ("R") хранящийся в регистре IDR, совпадает с номером сектора, +считанным с диска из поля идентификатора сектора, контроллер последовательно, +байт за байтом, запрашивает данные у процессора по шине данных и записывает +их в поле данных сектора на диск. После окончания записи данных текущий номер +сектора увеличивается на 1 и производится запись следующего поля данных. +Такую мультисекторную операцию записи контроллер продолжает до тех пор, пока +не получит сигнал ТС (конец счета). При поступлении сигнала ТС контроллер +продолжает запись данных в текущий сектор до его заполнения. Если контроллер +принимает сигнал ТС в процессе записи данных, то оставшееся поле данных +заполняется нулями. + Контроллер считывает идентификатор каждого сектора и производит +CRC-контроль считанных байт. Если он обнаруживает ошибку CRC в одном из +секторов, он устанавливает флаг DE (Data Error) в регистре ST1 и заканчивает +операцию (в регистре ST0 биты D7 и D6 устанавливаются в 0 и 1 +соответственно). + Команда записи во многом аналогична команде чтения данных. Ниже +перечислены все характеристики, аналогичные команде чтения данных: + * Количество передаваемых данных. + * Флаг EN (ENd of cylinder). + * Флаг ND (No Data). + * Пауза до отвода головки HUT. + * Информация, считываемая на фазе результата, если процессор прерывает + выполнение команды. + * Определение DTL, когда N=0 или N>0. + + В режиме записи данные от процессора или контроллера ПДП должны +приходить не реже 1 раза в 31 мксек. при одинарной плотности и 15 мксек. - +при двойной. В противном случае контроллер устанавливает флаг OR (Over Run) в +регистре ST1 и заканчивает операцию. + + Write Deleted Data Запись удаленных данных + ══════════════════ ═══════════════════════ + Команда аналогична команде Write Data за исключением того, что вместо +адресного маркера данных записывает адресный маркер удаленных данных. + + Read Deleted Data Чтение удаленных данных + ═════════════════ ═══════════════════════ + Команда аналогична команде Read Data за исключением случая, когда +контроллер обнаруживает адресный маркер данных в начале поля данных сектора. +Если бит SK=0, контроллер считывает все данные сектора, устанавливает флаг CM +в регистре ST2 и заканчивает операцию. Если бит SK=1, контроллер пропускает +этот сектор и переходит к чтению следующего. + + Read a Track Чтение дорожки + ════════════ ══════════════ + Команда подобна команде Read Data за исключением того, что данные будут +считываться непрерывно из каждого сектора дорожки. Сразу же после обнаружения +индексного импульса контроллер начинает считывать все поля данных на дорожке +как непрерывный блок данных. Если контроллер обнаруживает ошибку CRC в поле +идентификатора или данных, он продолжает считывать данные с дорожки. +Контроллер сравнивает информацию из поля идентификатора, считанную из каждого +сектора, со значением в IDR и устанавливает флаг ND в регистре ST1, если они +не совпадают. Биты МТ и SK не оказывают влияния на контроллер. + Выполнение команды заканчивается, когда контроллер считает ЕОТ секторов. +Если контроллер не нашел адресного маркера поля идентификатора до того, как +второй раз принял индексный импульс, он устанавливает флаг МА (Missing +Address Mark) в регистре ST1 и заканчивает операцию (в регистре ST0 +устанавливаются биты D7 и D6 в 0 и 1 соответственно). + + Read ID Чтение идентификатора + ═══════ ═════════════════════ + Эта команда используется для определения текущего положения головки +записи/чтения накопителя. Контроллер запоминает информацию, считанную из +первого встреченного поля идентификатора сектора. Если до прихода второго +индексного импульса контроллер не встретил адресного маркера поля +идентификатора, он устанавливает флаг МА в регистре ST1. Если же контроллер +не нашел данных, то он устанавливает флаг ND в регистре ST1 и операция +заканчивается. + + Format a Track Форматирование дорожки + ══════════════ ══════════════════════ + Команда форматирует всю дорожку. После обнаружения индексного импульса +на диск записываются следующие данные: GAPS, адресный маркер, поле +идентификатора и поле данных, соответствующие стандарту IBM System 34 +(одинарная плотность) и IBM System 3740 (двойная плотность). + Формат задается в команде следующими программируемыми значениями: + * N - число байт в секторе. + * SC - число секторов на цилиндре. + * GPL - длина межсекторного промежутка. + * D - байт для заполнения области данных. +Эти параметры передаются в контроллер процессором на фазе приказа. Поле +данных каждого сектора будет заполнено байтами D. Поле идентификатора для +каждого сектора задается процессором на фазе исполнения. Необходимы по 4 +значения для каждого сектора: + * C - номер цилиндра + * H - номер головки (поверхности) + * R - номер сектора + * N - код длины сектора +Это значит, что диск при необходимости, может быть отформатирован не +последовательными номерами секторов. + После форматирования каждого сектора процессор должен передать новые +значения C,H,R,N для каждого сектора на дорожке. Содержимое регистра R +увеличивается на 1 после форматирования каждого сектора, и, следовательно, +этот регистр будет содержать значение R+1 при считывании на фазе результата. +Этот процесс будет продолжаться для всей дорожки, пока второй раз не будет +обнаружен индексный импульс. После этого выполнение команды завершается. Если +при записи от накопителя принимается сигнал Fault, контроллер устанавливает +флаг ЕС в регистре ST0 и заканчивает операцию (биты D7 и D6 в регистре ST0 +устанавливаются в 0 и 1 соответственно). Отсутствие сигнала Ready с +накопителя в начале фазы исполнения также прекращает выполнение команды. + В таблице приведены соотношения между N, SC, GPL для различных размеров +секторов. + ╔════════════════════╦════════════════════╗ + ║ SD - (MFM = 0) ║ DD (MFM = 1) ║ + ╔══════╦════╬══════╦══════╦══════╬══════╦══════╦══════╣ + ║Сектор║ N ║ SC ║ GPL1 ║ GPL2 ║ SC ║ GPL1 ║ GPL2 ║ + ╠══════╬════╬══════╬══════╬══════╬══════╬══════╬══════╣ + ║ 128 ║ 0 ║ 1A ║ 07 ║ 1B ║ -- ║ -- ║ -- ║ + ║ 256 ║ 1 ║ 0F ║ 0E ║ 2A ║ 1A ║ 0E ║ 36 ║ + ║ 512 ║ 2 ║ 08 ║ 1B ║ 3A ║ 0F ║ 1B ║ 54 ║ + ║ 1024 ║ 3 ║ 04 ║ 47 ║ 8A ║ 08 ║ 3F ║ 74 ║ + ║ 2048 ║ 4 ║ 02 ║ C8 ║ FF ║ 04 ║ 99 ║ FF ║ + ║ 4096 ║ 5 ║ 01 ║ C8 ║ FF ║ 02 ║ C8 ║ FF ║ + ║ 8192 ║ 6 ║ -- ║ -- ║ -- ║ 01 ║ C8 ║ FF ║ + ╚══════╩════╩══════╩══════╩══════╩══════╩══════╩══════╝ + + + Scan Commands Команды сканирования + ═════════════ ════════════════════ + Команды сканирования позволяют считанные с диска данные сравнить с +данными, выдаваемые процессором (контроллером ПДП). Контроллер сравнивает +данные последовательно, байт за байтом и проверяет условия: + DD = DP DD <= DP DD >= DP +где DD - данные с диска; DP - данные от процессора. + После проверки всего сектора, если условие не выполняется, производится +инкремент номера сектора (R + STR -> R) и операция сканирования продолжается. +Операция будет продолжаться до тех пор, пока не произойдет одно из следующих +условий: + * выполнится условие сканирования (равно, больше или меньше) + * достигнут последний сектор (ЕОТ) + * принят сигнал ТС +Если условие сканирования удовлетворено, контроллер устанавливает флаг SH +(Scan Hit) в регистре ST2 и завершает команду. Если условие не удовлетворено +в промежутке между начальным сектором (заданным R) и последним сектором +цилиндра (ЕОТ), контроллер устанавливает флаг SN (Scan Not Satisfied) в +регистре ST2 и завершает команду. + Если во время операции поступил сигнал ТС от процессора или контроллера +ПДП, контроллер прекращает сравнение на текущем байте и завершает команду. + Ниже в таблице приведены состояния битов SH и SN после различных условий +сканирования: + ╔═══════════════════╦═══════╦═══════════╗ + ║ ║Рег.ST2║ ║ + ║ Сканирование до.. ╠═══╦═══╣ Примeчание║ + ║ ║ SN║ SH║ ║ + ╠═══════════════════╬═══╬═══╬═══════════╣ + ║ Равно ║ 0 ║ 1 ║ DD = DP ║ + ║ ║ 1 ║ 0 ║ DD <>DP ║ + ╠═══════════════════╬═══╬═══╬═══════════╣ + ║ Меньше или равно ║ 0 ║ 1 ║ DD = DP ║ + ║ ║ 0 ║ 0 ║ DD < DP ║ + ║ ║ 1 ║ 0 ║ DD > DP ║ + ╠═══════════════════╬═══╬═══╬═══════════╣ + ║ Больше или равно ║ 0 ║ 1 ║ DD = DP ║ + ║ ║ 0 ║ 0 ║ DD > DP ║ + ║ ║ 1 ║ 0 ║ DD < DP ║ + ╚═══════════════════╩═══╩═══╩═══════════╝ + + + Если контроллер обнаруживает адресный маркер удаленных данных в одном из +секторов и бит SK=0, он считает этот сектор последним сектором цилиндра, +устанавливает флаг CM (Control Mark) в регистре ST2 и завершает команду. Если +же бит SK=1, контроллер пропускает этот сектор и считывает следующий. В этом +случае контроллер устанавливает флаг CM в регистре ST2, сигнализирующий о +том, что был встречен удаленный сектор. + Когда вы программируете значения STP (STP=01 для обработки +последовательных секторов, STP=02 для чтения через один сектор) или МТ +(Multitrack), необходимо помнить, что последний сектор на дорожке должен быть +считан. Например, если STP = 02, МТ = 0, сектора пронумерованы +последовательно от 1 до 26, команду Scan начинаем с сектора 21, то успешно +будут обработаны сектора 21, 23 и 25. Далее сектор 26 будет пропущен, а затем +придет индексный импульс. Это вызовет ненормальное завершение операции. Если +бы ЕОТ равнялось 25, а сканирование бы начиналось с сектора 20, то операция +Scan завершилась бы успешно. + Аналогично командам чтения/записи, процессор или контроллер ПДП должен +обслуживать контроллер каждые 27 мксек. при одинарной плотности и 13 мксек. +при двойной. В противном случае контроллер выставит флаг OR (Over Run) в +регистре ST1 и прекратит выполнение команды. + + + Seek Команда позиционирования + ════ ════════════════════════ + Головка записи/чтения накопителя перемещается с цилиндра на цилиндр по +команде Seek. Контроллер сравнивает содержимое регистра PCN (Present Cylinder +Number), который хранит текущее положение головки и содержимое NCN (New +Cylinder Number) - новое положение головки, заданное в команде и в +зависимости от результата сравнения выполняет следующие действия: + * PCN < NCN - сигнал направления для накопителя устанавливается в "1" и + выдается импульс шага. + * PCN > NCN - сигнал направления для накопителя устанавливается в "0" и + выдается импульс шага. + + Скорость выдачи импульсов шага задается в команде Specify значением SRT +(Stepping Rate Time). После каждого импульса шага вновь сравниваются значения +PCN и NCN и когда PCN = NCN, контроллер устанавливает флаг SE (Seek End) в +регистре ST0 и завершает выполнение команды. + На фазе приказа контроллер находится в состоянии FDC Busy (занят), +однако на фазе исполнения контроллер переходит в состояние NON Busy (не +занят). Когда контроллер находится в состоянии NON Busy, ему можно задать +другие операции Seek и в этом случае команда позиционирования будет +выполняться одновременно для нескольких (до 4-х) накопителей. + Если перед началом фазы исполнения или во время исполнения команды Seek +накопитель находится в состоянии Not Ready (не готов), контроллер +устанавливает флаг NR (Not Ready) в регистре ST0 и команда завершается. + + Recalibrate Рекалибровка (откат) + ═══════════ ════════════════════ + Команда переустанавливает головку чтения/записи накопителя на +дорожку 0. Накопитель в этом случае должен выдать сигнал TR00. Контроллер +сбрасывает содержимое регистра PCN и проверяет сигнал TR00 с накопителя. Пока +этот сигнал имеет низкий уровень, контроллер устанавливает в "1" сигнал +направления Dir и выдает импульсы шага на накопитель. Когда сигнал TR00 +становится высоким, контроллер устанавливает флаг SE (Seek End) в регистре +ST0 и завершает команду. Если после выдачи 77 импульсов шага состояние +сигнала не изменилось, контроллер устанавливает флаги SE (Seek End) и EC +(Equipment Check) в регистр ST0 и команда завершается. Команда может +производить рекалибровку одновременно всех 4-х накопителей. Реакция на +исчезновение сигнала Ready с накопителя аналогична реакции в команде Seek. + + Sense Interrupt Status Считать состояние прерывания + ══════════════════════ ════════════════════════════ + Сигнал прерывания INT генерируется контроллером в следующих случаях: + 1. На фазе результата следующих команд: + * Read Data + * Read a Track + * Read ID + * Read Deleted Data + * Write Data + * Write Deleted Data + * Format a Track + * Scan Sommand + 2. Изменение сигнала Ready с накопителя + 3. В конце команд Seek или Recalibrate + 4. На фазе выполнения в режиме NON DMA +Прерывания в случаях (1) и (4) легко распознаются процессором, т.к. +производятся во время нормального исполнения команд. Однако прерывания в +случаях (2) и (3) могут быть идентифицированы процессором только путем +выполнения команды чтения состояния прерывания. Эта команда сбрасывает сигнал +прерывания и посредством битов 5-7 регистра ST0 процессор может определить +причину прерывания. + + ╔═════╦═══════════╦═════════════════════════════════╗ + ║ SE ║ INT Code ║ ║ + ╠═════╬═════╦═════╣ ║ + ║ бит ║ бит ║ бит ║ Причина прерывания ║ + ║ 5 ║ 6 ║ 7 ║ ║ + ╠═════╬═════╬═════╬═════════════════════════════════╣ + ║ 0 ║ 1 ║ 1 ║ Изменение сигнала Readu ║ + ║ ║ ║ ║ с накопителя ║ + ╠═════╬═════╬═════╬═════════════════════════════════╣ + ║ 1 ║ 0 ║ 0 ║ Нормальное завершение команд ║ + ║ ║ ║ ║ Seek и Recalibrate ║ + ╠═════╬═════╬═════╬═════════════════════════════════╣ + ║ 1 ║ 1 ║ 0 ║ Ошибочное завершение команд ║ + ║ ║ ║ ║ Seek и Recalibrate ║ + ╚═════╩═════╩═════╩═════════════════════════════════╝ + + Команды Seek и Recalibrate не имеют фазы результата, поэтому требуется +использование команды Sense Interrupt Status для их успешного завершения и +проверки положения головки накопителя (PCN). + + Specify Установить параметры накопителя + ═══════ ═══════════════════════════════ + Команда задает значения 3 временных интервалов - параметров накопителей: + * HUT - пауза до отвода головки. Задает время от окончания операции + чтения/записи до момента отвода головки от поверхности диска. + Время задается в единицах по 16 мсек. и лежит в пределах + 16..240 мсек. + * SRT - время шага головки. Задает время задержки между двумя + последовательными импульсами шага. Время задается в единицах + по 1 мсек. и лежит в пределах 1..16 мсек. + Внимание! Большие числа задают меньшее время шага: + 0FH - 1 мсек., 0EH - 2 мсек. и т.д. + * HLT - время подвода головки. Задает время между выдачей сигнала + подвода головки к диску и началом операции чтения/записи. + Задается в единицах по 2 мсек. и лежит в пределах 2..254 мсек. + Все временные интервалы, указанные выше, связаны с тактовой частотой +контроллера (CLK, выв.19) и приведены для случая, когда CLK = 8 МГц (203 мм. +диск). Если же CLK = 4 МГц (133 мм. диск), то все значения уменьшатся в 2 +раза. + Бит ND в команде осуществляет выбор режима ПДП для контроллера: если бит +ND=1, выбирается режим NON DMA (не-ПДП), если же ND=0, то выбирается режим +DMA (ПДП). + + Sense Drive Status Чтение состояния накопителя + ══════════════════ ═══════════════════════════ + Команда может быть использована процессором, когда ему необходимо узнать +состояние накопителя. Регистр ST3 содержит информацию о состоянии накопителя. + + Invalid Недопустимая команда + ═══════ ════════════════════ + Если в контроллер передается команда, не опознанная как одна из +вышеперечисленных, контроллер завершает команду. В этом случае прерывание не +генерируется. Биты 6 и 7 в регистре состояния (DIO и RQM) устанавливаются в +1, указывая процессору на необходимость выполнения фазы результата - чтения +регистра ST0. В регистре ST0 находится байт 80Н, показывающий недопустимую +команду. + Необходимо отметить, что после операций Seek и Recalibrate +(возникновения прерывания после окончания команды), контроллер должен +получить команду Sense Interrupt Status, иначе он воспримет следующую команду +как недопустимую. + Пользователь при необходимости может использовать эту команду, как +команду NOP (нет операции) для приведения контроллера в известное состояние +или в состояние без операции. + \ No newline at end of file diff --git a/docs/8272CMD.DOC b/docs/8272CMD.DOC new file mode 100644 index 0000000..5464f11 --- /dev/null +++ b/docs/8272CMD.DOC @@ -0,0 +1,144 @@ + + + + + Система команд контроллера НГМД i8272 + +╔═════════════╦═══╦═══════════════════════════════╦════════════════════════╗ +║ ║ R ║ Шина данных ║ ║ +║ Фаза ║ / ╠═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╣ Примечание ║ +║ ║ W ║ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 ║ ║ +║═════════════╬═══╬═══╧═══╧═══╧═══╧═══╧═══╧═══╧═══╬════════════════════════╣ +║ Приказ ║ W ║ Read/Write/Scan ║ Командное слово ║ +║ ║ ╟───┬───┬───┬───┬───┬───┬───┬───╢ (см. таблицу) ║ +║ ║ ║ 0 │ 0 │ 0 │ 0 │ 0 │HDS│DS0│DS1║ ║ +║ ║ ╟───┴───┴───┴───┴───┴───┴───┴───╢ ║ +║ ║ ║ C ║ ║ +║ ║ ║ H ║ ║ +║ ║ ║ R ║ ║ +║ ║ ║ N ║ ║ +║ ║ ║ EOT ║ ║ +║ ║ ║ GPL ║ ║ +║ ║ ║ DTL ║ ║ +╠═════════════╬═══╬═══════════════════════════════╬════════════════════════╣ +║ Исполнение ║ ║ Выполнение операции ║ ║ +╠═════════════╬═══╬═══════════════════════════════╬════════════════════════╣ +║ Результат ║ R ║ ST0 ║ ║ +║ ║ ║ ST1 ║ ║ +║ ║ ║ ST2 ║ ║ +║ ║ ║ C ║ ║ +║ ║ ║ H ║ ║ +║ ║ ║ R ║ ║ +║ ║ ║ N ║ ║ +╚═════════════╩═══╩═══════════════════════════════╩════════════════════════╝ + Командные слова + ╔══════════════════╦═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╦═══════╗ + ║ Команда ║ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 ║ Прим. ║ + ╠══════════════════╬═══╪═══╪═══╪═══╪═══╪═══╪═══╪═══╬═══════╣ + ║ Read Data ║ MT│MFM│ SK│ 0 │ 0 │ 1 │ 1 │ 0 ║ ║ + ║ Read Del.Data ║ MT│MFM│ SK│ 0 │ 1 │ 1 │ 0 │ 0 ║ ║ + ║ Write Data ║ MT│MFM│ SK│ 0 │ 0 │ 1 │ 0 │ 1 ║ ║ + ║ Write Del.Data ║ MT│MFM│ SK│ 0 │ 1 │ 0 │ 0 │ 1 ║ ║ + ║ Read a Track ║ MT│MFM│ SK│ 0 │ 0 │ 0 │ 1 │ 0 ║ ║ + ╠══════════════════╬═══╪═══╪═══╪═══╪═══╪═══╪═══╪═══╬═══════╣ + ║ Scan Equal ║ MT│MFM│ SK│ 1 │ 0 │ 0 │ 0 │ 1 ║ * ║ + ║ Scan Low or Eq. ║ MT│MFM│ SK│ 1 │ 1 │ 0 │ 0 │ 1 ║ * ║ + ║ Scan High or Eq. ║ MT│MFM│ SK│ 1 │ 1 │ 1 │ 0 │ 1 ║ * ║ + ╚══════════════════╩═══╧═══╧═══╧═══╧═══╧═══╧═══╧═══╩═══════╝ + * В командах сканирования последний байт приказа DTL заменяется на STD + + +╔═════════════╦═══╦═══════════════════════════════╦═══════════════════════╗ +║ ║ R ║ Шина данных ║ ║ +║ Фаза ║ / ╠═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╣ Примечание ║ +║ ║ W ║ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 ║ ║ +╠═════════════╩═══╩═══╧═══╧═══╧═══╧═══╧═══╧═══╧═══╩═════════════╦═════════╣ +║ Read ID ║ 4AH/0AH ║ +╠═════════════╦═══╦═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╦═════════════╩═════════╣ +║ Приказ ║ W ║ 0 │MFM│ 0 │ 0 │ 1 │ 0 │ 1 │ 0 ║ Командное слово ║ +║ ║ ╟───┼───┼───┼───┼───┼───┼───┼───╢ ║ +║ ║ ║ 0 │ 0 │ 0 │ 0 │ 0 │HDS│DS0│DS1║ ║ +╠═════════════╬═══╬═══╧═══╧═══╧═══╧═══╧═══╧═══╧═══╬═══════════════════════╣ +║ Исполнение ║ ║ Выполнение операции ║ ║ +╠═════════════╬═══╬═══════════════════════════════╬═══════════════════════╣ +║ Результат ║ R ║ ST0 ║ ║ +║ ║ ║ ST1 ║ ║ +║ ║ ║ ST2 ║ ║ +║ ║ ║ C ║ ║ +║ ║ ║ H ║ ║ +║ ║ ║ R ║ ║ +║ ║ ║ N ║ ║ +╠═════════════╩═══╩═══════════════════════════════╩═════════════╦═════════╣ +║ Format a Track ║ 4DH/0DH ║ +╠═════════════╦═══╦═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╦═════════════╩═════════╣ +║ Приказ ║ W ║ 0 │MFM│ 0 │ 0 │ 1 │ 1 │ 0 │ 1 ║ Командное слово ║ +║ ║ ╟───┼───┼───┼───┼───┼───┼───┼───╢ ║ +║ ║ ║ 0 │ 0 │ 0 │ 0 │ 0 │HDS│DS0│DS1║ ║ +║ ║ ╟───┴───┴───┴───┴───┴───┴───┴───╢ ║ +║ ║ ║ N ║ Размер сектора ║ +║ ║ ║ SC ║ Количество секторов ║ +║ ║ ║ GPL ║ Межсекторный GAP ║ +║ ║ ║ D ║ Заполнитель ║ +╠═════════════╬═══╬═══════════════════════════════╬═══════════════════════╣ +║ Исполнение ║ ║ Выполнение операции ║ ║ +╠═════════════╬═══╬═══════════════════════════════╬═══════════════════════╣ +║ Результат ║ R ║ ST0 ║ ║ +║ ║ ║ ST1 ║ ║ +║ ║ ║ ST2 ║ ║ +║ ║ ║ C ║ ║ +║ ║ ║ H ║ ║ +║ ║ ║ R ║ ║ +║ ║ ║ N ║ ║ +╠═════════════╩═══╩═══════════════════════════════╩═════════════════╦═════╣ +║ Recalibrate ║ 07H ║ +╠═════════════╦═══╦═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╦═════════════════╩═════╣ +║ Приказ ║ W ║ 0 │ 0 │ 0 │ 0 │ 0 │ 1 │ 1 │ 1 ║ Командное слово ║ +║ ║ ╟───┼───┼───┼───┼───┼───┼───┼───╢ ║ +║ ║ ║ 0 │ 0 │ 0 │ 0 │ 0 │HDS│DS0│DS1║ ║ +╠═════════════╬═══╬═══╧═══╧═══╧═══╧═══╧═══╧═══╧═══╬═══════════════════════╣ +║ Исполнение ║ ║ Выполнение операции ║ Фазы результата нет ║ +╠═════════════╩═══╩═══════════════════════════════╩═════════════════╦═════╣ +║ Sense Interrupt Status ║ 08H ║ +╠═════════════╦═══╦═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╦═════════════════╩═════╣ +║ Приказ ║ W ║ 0 │ 0 │ 0 │ 0 │ 1 │ 0 │ 0 │ 0 ║ Командное слово ║ +╠═════════════╬═══╬═══╧═══╧═══╧═══╧═══╧═══╧═══╧═══╬═══════════════════════╣ +║ Результат ║ R ║ ST0 ║ Фазы исполнения нет ║ +║ ║ ║ PCN ║ ║ +╠═════════════╩═══╩═══════════════════════════════╩═════════════════╦═════╣ +║ Specify ║ 03H ║ +╠═════════════╦═══╦═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╦═════════════════╩═════╣ +║ Приказ ║ W ║ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 1 │ 1 ║ Командное слово ║ +║ ║ ╟───┴───┴───┴───┼───┴───┴───┴───╢═══════════════════════╣ +║ ║ ║ SRT │ HUT ║ Нет фаз результата ║ +║ ║ ╟───────────────┴───────────┬───╢ и исполнения ║ +║ ║ ║ HLT │ ND║ ║ +╚═════════════╩═══╩═══════════════════════════╧═══╩═══════════════════════╝ + +╔═══════════════════════════════════════════════════════════════════╦═════╗ +║ Sense Drive Status ║ 04H ║ +╠═════════════╦═══╦═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╦═════════════════╩═════╣ +║ Приказ ║ W ║ 0 │ 0 │ 0 │ 0 │ 1 │ 1 │ 0 │ 1 ║ Командное слово ║ +║ ║ ╟───┼───┼───┼───┼───┼───┼───┼───╢ ║ +║ ║ ║ 0 │ 0 │ 0 │ 0 │ 0 │HDS│DS0│DS1║ ║ +╠═════════════╬═══╬═══╧═══╧═══╧═══╧═══╧═══╧═══╧═══╬═══════════════════════╣ +║ Результат ║ R ║ ST3 ║ Фазы исполнения нет ║ +╠═════════════╩═══╩═══════════════════════════════╩═════════════════╦═════╣ +║ Seek ║ 0FH ║ +╠═════════════╦═══╦═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╦═════════════════╩═════╣ +║ Приказ ║ W ║ 0 │ 0 │ 0 │ 0 │ 1 │ 1 │ 1 │ 1 ║ Командное слово ║ +║ ║ ╟───┼───┼───┼───┼───┼───┼───┼───╢ ║ +║ ║ ║ 0 │ 0 │ 0 │ 0 │ 0 │HDS│DS0│DS1║ ║ +║ ║ ╠═══╧═══╧═══╧═══╧═══╧═══╧═══╧═══╣ ║ +║ ║ ║ NCN ║ ║ +╠═════════════╬═══╬═══════════════════════════════╬═══════════════════════╣ +║ Исполнение ║ ║ Выполнение операции ║ Фазы результата нет ║ +║ ║ ║ ║ Генерирует прерывание ║ +╠═════════════╩═══╩═══════════════════════════════╩═════════════════╦═════╣ +║ Invalid ║ XXH ║ +╠═════════════╦═══╦═══════════════════════════════╦═════════════════╩═════╣ +║ Приказ ║ W ║ Недопустимый код операции ║ ║ +╠═════════════╬═══╬═══════════════════════════════╬═══════════════════════╣ +║ Результат ║ R ║ ST0 ║ ST0=80H - признак ║ +║ ║ ║ ║ ошибки ║ +╚═════════════╩═══╩═══════════════════════════════╩═══════════════════════╝ + \ No newline at end of file diff --git a/docs/8272FORM.DOC b/docs/8272FORM.DOC new file mode 100644 index 0000000..4bd0d5b --- /dev/null +++ b/docs/8272FORM.DOC @@ -0,0 +1,74 @@ + ╔═════════════════════════════════════════════════════╗ + ║ Формат хранения информации на гибком диске. ║ + ║ Стандарт IBM System 34 (SD) и IBM System 3740 (DD). ║ + ╚═════════════════════════════════════════════════════╝ + + ╔═════╗ <-- Индекс (начало дорожки). Hex Hex + ║ ║ ╔════╦════╗ + ║ ║ ║ SD ║ DD ║ + ║ ║ <-- Постиндексный промежуток ╠════╬════╣ + ║ ║ Длина промежутка (байт) - ║ 28 ║ 50 ║ + ║ ║ Записывается байт - ║ FF ║ 4E ║ + ╠═════╣ ╚════╩════╝ + ║ ║ <-- Код синхронизации ╔════╦════╗ + ║ ║ Длина поля (байт) - ║ 6 ║ 0C ║ + ║ ║ Записывается байт - ║ 00 ║ 00 ║ + ╠═════╣ ╠════╬════╣ + ║ ║ <-- Адресная метка индекса ║ ║ ║ + ║ ║ (4 байта) ║ FC ║ C2*║ + ║ ║ Записывается байт - ║ ти ║ C2*║ + ║ ║ ║(D7)║ C2*║ + ║ ║ ║ ║ FC ║ + ╠═════╣ ╠════╬════╣ + ║ ║ <-- Промежуток (байт) - ║ 1A ║ 32 ║ + ║ ║ Записывается байт - ║ FF ║ 4E ║ + ╚═════╝ ╚════╩════╝ +Далее циклическое повторение для каждого сектора: + ╔═════╗ ╔════╦════╗ + ║ ║ <-- Код синхронизации. Длина: ║ 6 ║ 0C ║ + ║ ║ Записывается байт - ║ 00 ║ 00 ║ + ╠═════╣ ╠════╬════╣ + ║ ║ <-- Адресная метка идентификатора ║ FE ║ A1*║ + ║ ║ (4 байта) ║ ти ║ A1*║ + ║ ║ ║(C7)║ A1*║ + ║ ║ ║ ║ FE ║ + ╠═════╣ ╚════╩════╝ + ║ C ║ <-- Номер дорожки + ╠═════╣ + ║ H ║ <-- Номер поверхности + ╠═════╣ + ║ R ║ <-- Номер сектора + ╠═════╣ + ║ N ║ <-- Код длины сектора: + ║ ║ 00 - 128, 01 - 256, 02 - 512, 03 - 1024 и т.д. + ╠═════╣ ╔════╦════╗ + ║ ║ <-- Промежуток. Длина: ║ FE ║ 4E ║ + ║ ║ Записывается байт - ║ 0B ║ 16 ║ + ║ ║ ║ ║ ║ + ║ ║ ║ ║ ║ + ╠═════╣ ╚════╩════╝ + ║ ║ <-- 2 байта CRC - контроля + ╠═════╣ ╔════╦════╗ + ║ ║ <-- Код синхронизации. Длина: ║ 0B ║ 16 ║ + ║ ║ Записывается байт - ║ FF ║ 4E ║ + ╠═════╣ ╠════╬════╣ + ║ ║ <-- Адресная метка данных ║ ти ║ A1*║ + ║ ║ ║(C7)║ A1*║ + ║ ║ ║ ║ A1*║ + ║ ║ Для данных - ║ FB ║ FB ║ + ║ ║ Для удаленных данных - ║ F8 ║ F8 ║ + ╠═════╣ ╚════╩════╝ + ║ ║ <-- Поле данных: 128, 256, 512 ... байт. + ╠═════╣ + ║ ║ <-- 2 байта CRC - контроля + ╠═════╣ + ║ ║ <-- Постсекторный промежуток. ╔════╦════╗ + ║ ║ Записывается байт ║ FF ║ 4E ║ + ║ ║ Длина промежутка (байт): ╠════╬════╣ + ║ ║ 8 секторов ║ 3A ║ 74 ║ + ║ ║ 15 секторов ║ 2A ║ 54 ║ + ║ ║ 26 секторов ║ 1B ║ 36 ║ + ╚═════╝ ╚════╩════╝ + ти - тактовые импульсы + A1*, C2* - запись с выпадением тактовых импульсов + \ No newline at end of file diff --git a/docs/8272STAT.DOC b/docs/8272STAT.DOC new file mode 100644 index 0000000..6cd8176 --- /dev/null +++ b/docs/8272STAT.DOC @@ -0,0 +1,109 @@ +╔══════════════════════════════════════════════════════════════════════════════════════════════════╗ +║ Регистры состояния ST0 - ST3 ║ +╠════╦═════════════╦══════╦════════════════════════════════════════════════════════════════════════╣ +║ Бит║ Название ║ Обозн║ Описание ║ +╠════╩═════════════╩══════╩════════════════════════════════════════════════════════════════════════╣ +║ Регистр состояния ST0 ║ +╠════╦═════════════╦══════╦════════════════════════════════════════════════════════════════════════╣ +║ D7 ║ Interrupt ║ IC ║ Биты D7,D6 совместно показывают исход команды, вызвавшей прерывание: ║ +║ D6 ║ Code ║ ║ 00 - нормальное завершение команды (NT - Normal Termination) ║ +║ ║ ║ ║ 01 - ошибочное завершение команды (AT - Abnormal Terminated) ║ +║ ║ ║ ║ команда была начата, но не выполнена успешно. ║ +║ ║ ║ ║ 10 - недопустимая команда (IC - Invalid Command). ║ +║ ║ ║ ║ 11 - ненормальное завершение команды из-за изменения сигнала Ready║ +║ ║ ║ ║ с накопителя. ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D5 ║ Seek End ║ SE ║ Когда контроллер выполнил команду Seek, этот бит установлен в "1". ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D4 ║ Equipment ║ EC ║ Если с накопителя пришел сигнал Fault или после 77 шагов не получен ║ +║ ║ Check ║ ║ сигнал TR00, этот бит устанавливается в "1". ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D3 ║ Not Ready ║ NR ║ Если накопитель в состоянии Not Ready и задается команда чтения ║ +║ ║ ║ ║ или записи, этот бит устанавливается в "1". ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D2 ║ Head Address║ HD ║ Флаг используется для указания состояния головки при прерывании. ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D1 ║ Unit ║ US1 ║ Два бита указывают номер накопителя при прерывании. ║ +║ D0 ║ Select ║ US0 ║ ║ +╠════╩═════════════╩══════╩════════════════════════════════════════════════════════════════════════╣ +║ Регистр состояния ST1 ║ +╠════╦═════════════╦══════╦════════════════════════════════════════════════════════════════════════╣ +║ D7 ║ End OF ║ EN ║ Когда контроллер пытается получить доступ к сектору с номером, ║ +║ ║ Cylinder ║ ║ превышающим номер последнего сектора цилиндра, флаг устанавливается. ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D6 ║ ----- ║ ║ Не используется, всегда = 0 ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D5 ║ Data Error ║ DE ║ Флаг устанавливается при выявлении ошибки CRC в полях ║ +║ ║ ║ ║ данных или идентификатора сектора. ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D4 ║ Over Run ║ OR ║ Флаг устанавливается, если контроллер не обслужен системой ║ +║ ║ ║ ║ во время передачи данных (потеря данных). ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D3 ║ ----- ║ ║ Не используется, всегда = 0. ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D2 ║ No Data ║ ND ║ В командах Read Data, Write Deleted Data или Scan если ║ +║ ║ ║ ║ контроллер не может найти сектор, указанный рег. IDR, флаг = "1". ║ +║ ║ ║ ╠════════════════════════════════════════════════════════════════════════╣ +║ ║ ║ ║ В команде Read ID, если контроллер не может считать поле ║ +║ ║ ║ ║ идентификатора сектора без ошибки, флаг устанавливается в "1". ║ +║ ║ ║ ╠════════════════════════════════════════════════════════════════════════╣ +║ ║ ║ ║ В команде Read a Cylinder, если начальный сектор не найден, ║ +║ ║ ║ ║ флаг устанавливается в "1". ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D1 ║ Not ║ NW ║ В командах записи и форматирования, если контроллер обнаруживает ║ +║ ║ Writable ║ ║ сигнал защиты от записи с накопителя, флаг устанавливается. ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D0 ║ Missing ║ MA ║ Если не найден адресный маркер идентификатора сектора до прихода ║ +║ ║ Address ║ ║ второго индексного импульса, флаг устанавливается в "1". ║ +║ ║ Mark ║ ╠════════════════════════════════════════════════════════════════════════╣ +║ ║ ║ ║ Если не обнаружен адресный маркер данных или удаленных данных, флаг ║ +║ ║ ║ ║ устанавливается. При этом устанавливается флаг MD в регистре ST2. ║ +╚════╩═════════════╩══════╩════════════════════════════════════════════════════════════════════════╝ +╔════╦═════════════╦══════╦════════════════════════════════════════════════════════════════════════╗ +║ Бит║ Название ║ Обозн║ Описание ║ +╠════╩═════════════╩══════╩════════════════════════════════════════════════════════════════════════╣ +║ Регистр состояния ST2 ║ +╠════╦═════════════╦══════╦════════════════════════════════════════════════════════════════════════╣ +║ D7 ║ ------ ║ ║ Не используется, всегда = 0. ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D6 ║ Control ║ CM ║ В командах Read Data и Scan при обнаружении сектора с ║ +║ ║ Mark ║ ║ адресным маркером удаленных данных флаг устанавливается в "1". ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D5 ║ Data Error ║ DD ║ Флаг устанавливается в "1" при обнаружении ошибки CRC ║ +║ ║ in Data ║ ║ в поле данных сектора. ║ +║ ║ Field ║ ║ ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D4 ║ Wrong ║ WC ║ Устанавливается совместно с битом ND, если содержимое ║ +║ ║ Cylinder ║ ║ регистра С отличается от содержимого регистра IDR. ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D3 ║ Scan Equal ║ SH ║ В командах Scan при удовлетворении условия "равно" ║ +║ ║ Hit ║ ║ этот бит устанавливается в "1". ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D2 ║ Scan Not ║ SN ║ В командах Scan, если не найден сектор,отвечающий ║ +║ ║ Satisfied ║ ║ заданному условию, флаг устанавливается в "1". ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D1 ║ Bad ║ BC ║ Устанавливается совместно с битом ND, если содержимое ║ +║ ║ Cylinder ║ ║ регистра С отличается от содержтмого IDR и С = 0FFH. ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D0 ║ Missing ║ MD ║ Если при чтении не встречен адресный маркер данных или ║ +║ ║ Address Mark║ ║ адресный маркер удаленных данных, флаг устанавливается в "1". ║ +║ ║in Data Field║ ║ ║ +╠════╩═════════════╩══════╩════════════════════════════════════════════════════════════════════════╣ +║ Регистр состояния ST3 ║ +╠════╦═════════════╦══════╦════════════════════════════════════════════════════════════════════════╣ +║ D7 ║ Fault ║ FT ║ Отражает состояние сигнала Fault с накопителя. ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D6 ║ Write ║ WP ║ Отражает состояние сигнала Write Protect (защита от записи) ║ +║ ║ Protect ║ ║ с накопителя. ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D5 ║ Ready ║ RDY ║ Отражает состояние сигнала Ready с накопителя. ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D4 ║ Track 00 ║ T0 ║ Отражает состояние сигнала Track 00 с накопителя. ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D3 ║ Two Side ║ TS ║ Отражает состояние сигнала Two Side с накопителя. ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D2 ║ Head Address║ HD ║ Указывает на выбранную поверхность диска. ║ +╠════╬═════════════╬══════╬════════════════════════════════════════════════════════════════════════╣ +║ D1 ║ Unit ║ US1 ║ Два бита показывают выбранный накопитель. ║ +║ D0 ║ Select ║ US0 ║ ║ +╚════╩═════════════╩══════╩════════════════════════════════════════════════════════════════════════╝ diff --git a/docs/I8272.DOC b/docs/I8272.DOC new file mode 100644 index 0000000..7fa9dd2 --- /dev/null +++ b/docs/I8272.DOC @@ -0,0 +1,2194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INTEL + + 8272 + + SINGLE/DOUBLE DENSITY FLOPPY DISK + + CONTROLLER. + + + + + + + + + + + + + + + + + █ IBM Compatible in Both Single and █ Data Transfers in DMA or Non-DMA + Double Density Recording Formats Mode + + █ Programmable Data Record Lengths : █ Parallel Seek Operations on Up to + 128,256,512, or 1024 Bytes/Sector Four Drives + + █ Drive Up to 4 Floppy Disks █ Compatible with Most + Microprocessors Including 8080A, + █ Data Scan Capability - Will Scan a 8085A,8086 and 8088 + Single Sector or an Entire Cylinder's + Worth of Data Fields, Comparing on a █ Single-Phase 8 MHz Clock + Byte by Byte Basics, Data in the + Processor's Memory with Data Read █ Single +5 Volt Power Supply + from the Diskette + █ Available in 40-Pin Plastic Dual-in + -line Package + + + + + + + The 8272 is an LSI Floppy Disk Controller (FDC) Chip, WHICH contains the + circulty and control functions for interfacing a processor to 4 Floppy Disk + Drives. It is capable of supporting either IBM 3740 single density format + (FM),or IBM System 34 Double Density format (MFM) including double sided + recording. The 8272 provides control signals which simlify the design of an + external phase locked loop, and write precompensation circultry. The FDC + simplifies and hanles most of the burdens associated with implementing + a Floppy Disk Drive Interface. + + + + + +_______________________________________________________________________________ + + + PIN CONFIGURATION + + + ┌───┐ ┌────┐ + RESET──┤1 └───┘ 40 ├──Vcc + _RD──┤2 39 ├──_RW/SEEK + _WR──┤3 38 ├──LCT/DIR + _CS──┤4 37 ├──FR/STP + A0──┤5 36 ├──MDL + DB0──┤6 35 ├─RDY + DB1──┤7 34 ├──WP/TS + DB2──┤8 33 ├──FLT/TRK0 + DB3──┤9 32 ├──PS0 + DB4──┤10 31 ├──PS1 + DB5──┤11 30 ├──WR DATA + DB6──┤12 29 ├──DS0 + DB7──┤13 28 ├──DS1 + DRQ──┤14 27 ├──HDSEL + _DACK──┤15 26 ├──MFM + TC──┤16 25 ├──WE + IDX──┤17 24 ├──Vc0 + INT──┤18 23 ├──RD DATA + CLR──┤19 22 ├──DW + GND──┤20 21 ├──WR CLK + └────────────┘ + + + + + + + + 8272 INTERNAL BLOCK DIAGRAM + + + + + + + │ │ ┌──────────┐ + ┌───────┐ │ │ │ │ + /__\ │ │ /__\ │ │ /__\ │ │ + DB0-7<____>│ DATA │<___ >│8│<____>│ │ + \ / │ BUS │ \ / │2│ \ / │REGISTERS │ + │ BUFFER│ │7│ │ │ + │ │ │2│ │ │ + │ │ │ │ │ │ + └───────┘ │I│ │ │ + ─────┐ │N│ └──────────┘ + TERMINAL │ │T│ + COUNT \│ / │E│ ┌──────────┐ + \/ │R│ │ SERIAL │<------- WR CLOCK + ┌────────┐ │N│ │ INTERFACE│-------> WR DATA + DRQ<---│ │ │A│ /__\ │CONTROLLER│-------> WR ENABLE + DACK--->. READ │ │L│<____>│ │-------> PRE-SHIFT0 + INT<---│ WRITE │ │ │ \ / │ │-------> PRE-SHIFT1 + ID--->. DMA │ /__\ │B│ │ │<------- READ DATA + WR--->. CONTROL│<____>│U│ │ │<------- DATA WINDOW + A0--->│ LOGIC │ \ / │S│ └──────────┘-------> Vco SYNC + RESET--->│ │ │ │ ┌──────────┐ + │ │ │ │ │ │ ┌─────┐ + └───.────┘ │ │ │ │ /__│ │ + /│\ │ │ │ DRIVE │<___│INPUT│ + │ │ │ /__\ │INTERFACE │ \ │ PORT│ + │ │ │<____>│CONTROLLER│ │ │ + │ │ │ \ / │ │ └─────┘ + CS ─────┘ │ │ │ │ /\ ┌─────┐ + │ │ │ │<-->│ │-->DRIVE SEL0 + │ │ └──────────┘ \/ │ OUT │-->DRIVE SEL1 + │ │ │ │-->MFM MODE + CLK ---> │ │ │ PORT│-->R/W SEEK + Vcc ---> │ │-->HEAD LOAD + GND ---> │ │-->HEAD SELECT + │ │-->LOW + │ │ CURRENT/DIRECTION + └─────┘-->FAULT RESET/STEP + + + + + + + + + + 8272 SYSTEM BLOCK DIAGRAM + + + + + ┌──────┐ + │ │ + │ CPU │ + │ │ + └──────┘ + ^ + / \ + / \ + | | + | | + \ / + \ / +  + ──────────────────────────────────────────────────────── + SYSTEM BUS + ──────────────────────────────────────────────────────── + ^ ^ + / \ / \ + / \ / \ + | | | | + | | | | + \ / \ / + \ / \ / +   + ┌──────────┐ ┌──────────┐ DATA ┌───┐ ┌──────────┐ + │ │ DRQ │ │ WINDOW │ │ │ ──┤ + │ │<--------│ │<-----------│FLL│---│ │ + │ │ │ │ │ │ | │ + │ 8237 │ │ 8272 │ └───┘ | │ DRIVE │ + │ DMA │ _DACK │ │ RD DATA | │ │ + │CONTROLLER│-------->│ FDC │<------------------ │INTERFACE + │ │ │ │ WR DATA │ │ + │ │ │ │------------------->│ │ + │ │ │ │ / │ │ + │ │-------->│ │ / -----------------│ │ + └──────────┘ TC │ │< INPUT CONTROL │ │ + │ │ \ -----------------│ │ + (TERMINAL COUNT)│ │ \ │ │ + │ │ \ │ │ + │ │------------------\ │ │ + │ │ OUTPUT CONTROL >│ │ + └──────────┘------------------/ └──────────┘ + / + + + DESCRIPTION + + Hand-shaking signals are provided in the 8272 which make DMA operation + easy to incorporate with the aid of an external DMA Controller chip, such + as the 8237. The FDC will operate in einther DMA or Non-DMA mode. In the + Non-DMA mode,the FDC generates interrupts to the processor for every transfer + of data byte between the CPU and 8272. In the DMA mode, the processor need + only load command into the FDC and all data transfers occur under control of + the 8272 and DMA controller. + + There are 15 separate commands which the 8272 will execute. Each of these + commands require multiple 8-bit bytes to fully specify the operation which + the processor wishes the FDC to perform. The following commands are available: + + Read Data Write Data + Read ID Format a Track + Read Deleted Data Write Deleted Data + Read a Track Seek + Scan Equal Recalibrate (Restore to Track 0) + Scan High or Equal Sense Interrupt Status + Scan Low or Equal + Specify Sense Drive Status + + + + + FEATURES + + Addres mark detection circultry is internal to the FDC which simlifies the + phase locked loop and read electronics. The track stopping rate, head load + time, and head unload time may be programmed by user. The 8272 offers many + additional features such as multiple sector transfers in both read and write + modes with a single command, and full IBM compatibillity in both single (FM) + and double density (MFM) modes. + + + 8272 REGISTERS - CPU INTERFACE + + The 8272 contain two registers which may accessed by the main system + processor: a Status Register and a Data Register. The 8-bit Main Status + Register contains the status information of the FDC ,and may be accessed at + any time. The 8-bit Data Register ( actually consists of several registers in + a stack with only one register presented to the data bus at time), stores + data ,commands,parameters, and FDD status information. Data bytes are read + out of, or written into, the Data Register in order to program or obtain the + results after execution of command. The Status Register may only be read and + is used to facilitate the transfer of data between the processor and 8272. + + The relationship between the Status/Data registers and the signals _RD,_WR, + and A0 is shown below. + + ┌───┬─────┬─────┬───────────────────────────┐ + │A0 │ _RD │ _WR │ FUNCTION │ + ╞═══╪═════╪═════╪═══════════════════════════╡ + │ 0 │ 0 │ 1 │ Read Main Status │ + │ │ │ │ Register │ + ╞═══╪═════╪═════╪═══════════════════════════╡ + │ 0 │ 1 │ 0 │ illegal │ + ╞═══╪═════╪═════╪═══════════════════════════╡ + │ 0 │ 0 │ 0 │ illegal │ + ╞═══╪═════╪═════╪═══════════════════════════╡ + │ 1 │ 0 │ 0 │ illegal │ + ╞═══╪═════╪═════╪═══════════════════════════╡ + │ 1 │ 0 │ 1 │ Read from Data Register │ + ╞═══╪═════╪═════╪═══════════════════════════╡ + │ 1 │ 1 │ 0 │ Write into Data Register │ + │ │ │ │ │ + └───┴─────┴─────┴───────────────────────────┘ + + + + The bits in the Main Status Register are defined as follows: + + ┌─────────────┬────────────┬──────────┬─────────────────────────┐ + │ BIT NUMBER │ NAME │ SYMBOL │ DESCRIPTION │ + ├─────────────┼────────────┼──────────┼─────────────────────────┤ + │ DB0 │ FDD0 Busy │ D0B │ FDD number 0 is in the│ + │ │ │ │ seek mode. │ + ├─────────────┼────────────┼──────────┼─────────────────────────┤ + │ DB1 │ FDD1 Busy │ D1B │ FDD number 1 is in the│ + │ │ │ │ seek mode. │ + ├─────────────┼────────────┼──────────┼─────────────────────────┤ + │ DB2 │ FDD2 Busy │ D2B │ FDD number 2 is in the│ + │ │ │ │ seek mode │ + ├─────────────┼────────────┼──────────┼─────────────────────────┤ + │ DB3 │ FDD3 Busy │ D30 │ FDD number 3 is in the│ + │ │ │ │ seek mode │ + ├─────────────┼────────────┼──────────┼─────────────────────────┤ + │ DB4 │ FDD4 Busy │ CB │ A read or write command│ + │ │ │ │ is in progress │ + ├─────────────┼────────────┼──────────┼─────────────────────────┤ + │ DB5 │ Non - DMA │ NDM │ The FDC is in the non -│ + │ │ mode │ │ DMA mode. This bit is │ + │ │ │ │ set only during the │ + │ │ │ │ execution phase in │ + │ │ │ │ non-DMA mode.Transitien│ + │ │ │ │ ts "G" state indicates │ + │ │ │ │ execution phase has │ + │ │ │ │ ended │ + ├─────────────┼────────────┼──────────┼─────────────────────────┤ + │ DB6 │ Data Input │ DIO │ Indicates direction of │ + │ │ -Output │ │ data transfer between │ + │ │ │ │ FDC and Data Register. │ + │ │ │ │ If DIO is "1",then │ + │ │ │ │ transfer is from Data │ + │ │ │ │ Register to the │ + │ │ │ │ processor.If DIO is "0",│ + │ │ │ │ then transfer is from │ + │ │ │ │ the Processor to Data │ + │ │ │ │ Register. │ + ├─────────────┼────────────┼──────────┼─────────────────────────┤ + │ DB7 │ Request for│ RQM │ Indicates Data Register │ + │ │ │ │ is ready to send or │ + │ │ Master │ │ receive data to or from │ + │ │ │ │ the Processor.Both bits │ + │ │ │ │ DIO and RQM should be │ + │ │ │ │ used to perfom the │ + │ │ │ │ handshaking functios of │ + │ │ │ │ "ready" and "direction" │ + │ │ │ │ to the processor. │ + └─────────────┴────────────┴──────────┴─────────────────────────┘ + + + + + + PIN DESCRIPTION + ┌──────────────┬───────┬─────────────────┬──────────────────────────────────┐ + │ │ │ │ │ + │ PIN │ I/O │ CONNECTION │ DESCRIPTION │ + ├─────┬────────┤ │ │ │ + │ │ │ │ TO │ │ + │ NO. │ SYMBOL │ │ │ │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ 1 │ RST │ I │ mP │ Reset Places FDC in idts │ + │ │ │ │ │ state Resets output lines to │ + │ │ │ │ │ FDD is "0" (low) │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ Read:Control signal for │ + │ 2 │ _RD │ I* │ mP │ transfer of data from FDC to │ + │ │ │ │ │ Data Bus, when "0" (low) │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ Write: Control signal for │ + │ 3 │ _WR │ I* │ mP │ transfer of data to FDC via Data │ + │ │ │ │ │ Bus, when "0" (low) │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ 4 │ _CS │ I │ mP │ Chip Select: IC selected │ + │ │ │ │ │ when "0" (low), allowing │ + │ │ │ │ │ _RD and _WR to be enabled │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ 5 │ A0 │ I* │ mP │ Data/Status Reg Select: │ + │ │ │ │ │ Select Data Reg (A0=1) or │ + │ │ │ │ │ Status Reg (A0=0) │ + │ │ │ │ │ content be sent to Data Bus │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │6-13 │DB0-DB7 │ I/O* │ mP │ Data Bus: Bidirectional │ + │ │ │ │ │ 8 - Bit Data Bus │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ 14 │ DRQ │ O │ DMA │ Data DMA Request: DMA │ + │ │ │ │ │ Request is being made by │ + │ │ │ │ │ FDC when DRQ "1" │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ 15 │_DACK │ I │ DMA │ DMA Acknowledge: DMA │ + │ │ │ │ │ cycle is active when "0" │ + │ │ │ │ │ (low) and Controller is │ + │ │ │ │ │ performing DMA transfer │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ 16 │ TC │ I │ DMA │ Terminal Count: Indicates │ + │ │ │ │ │ the termination of a DMA │ + │ │ │ │ │ transfer when "1" (high) │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ │ + │ 17 │ IDX │ I │ FDD │ Index: Indicates the beginning │ + │ │ │ │ │ of a disk track │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ │ + │ 18 │ INT │ O │ mP │ Interrupt: Interrupt Request │ + │ │ │ │ │ Generated by FDC │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ │ + │ 19 │ CLK │ I │ │ Check: Single Phase 6MHz │ + │ │ │ │ │ Squarewave Check │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ │ + │ 20 │ CND │ │ │ Ground: D.C. Power Return │ + └─────┴────────┴───────┴─────────────────┴──────────────────────────────────┘ + Note * :Disabled when _CS = 1. + + ┌──────────────┬───────┬─────────────────┬──────────────────────────────────┐ + │ │ │ │ │ + │ PIN │ I/O │ CONNECTION │ DESCRIPTION │ + ├─────┬────────┤ │ │ │ + │ │ │ │ TO │ │ + │ NO. │ SYMBOL │ │ │ │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ 40 │ Vcc │ │ │ POWER │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ Read Write/SEEK. When "1" │ + │ 39 │_RWseek │ O │ FDD │ (high) seek mods selected and │ + │ │ │ │ │ when "0" (low) Read/Write │ + │ │ │ │ │ mode selected │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ FDD │ Low Current direction.Lawers │ + │ 38 │ LGT/DIR│ O │ │ Write current on inner tracks │ + │ │ │ │ │ in Read/Write mode,determines │ + │ │ │ │ │ direction head will step │ + │ │ │ │ │ in Seek mode │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ Fault Reset/Step: Resets fault │ + │ 37 │ FR/STP │ O │ FDD │ FF in FDD in Read/Write │ + │ │ │ │ │ mode, provides step pulses to │ + │ │ │ │ │ move head to another cylinder │ + │ │ │ │ │ in Seek mode │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ Head Load: Command which │ + │ 36 │ HDL │ O │ FDD │ causes read/write head in FDD │ + │ │ │ │ │ to contact diskette │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ Ready: Indicates FDD is ready │ + │ 35 │ RDY │ I │ FDD │ to send or receive data │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ 34 │ WP/TS │ I │ FDD │ Write Protect/Two-Side: │ + │ │ │ │ │ Senses Write Protect status in │ + │ │ │ │ │ Read/Write mode,and Two │ + │ │ │ │ │ Side Media in Seek mode │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ Fault/Track 0: Senses FDD │ + │ 33 │FLT/TRK0│ I │ FDD │ fault condition in Read/Write │ + │ │ │ │ │ mode and Track 0 condition │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ Precompensation (pre-shift): │ + │31,32│PS1,PS2 │ O │ FDD │ Write precompensation status │ + │ │ │ │ │ during MFM mode, Determines │ + │ │ │ │ │ early,late,and normal times. │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ Write Data: Serial clock and │ + │ 30 │WR DATA │ O │ FDD │ data bits to FDD │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ │ + │28,29│DS1,DS0 │ O │ FDD │ Drive Select: Selects FDD until │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ 27 │ HDSEL │ O │ FDD │ Head Select: Head 1 selected │ + │ │ │ │ │ when "1" (high) Head 0 │ + │ │ │ │ │ selected when "0" (low) │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ 26 │ MFM │ O │ FLL │ MFM Mode. MFM mode when │ + │ │ │ │ │ "1", FM mode when "0" │ + └─────┴────────┴───────┴─────────────────┴──────────────────────────────────┘ + + + + ┌─────┬────────┬───────┬─────────────────┬──────────────────────────────────┐ + │ │ │ │ │ Write Enable: Enables write │ + │ 25 │ WE │ O │ FDD │ data into FDD │ + │ │ │ │ │ │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ VCO Sync: Inhibits VCO in │ + │ 24 │ VCO │ O │ FLL │ FLL when "0" (low), enables │ + │ │ │ │ │ VCO when "1" │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ Read Data. Read data from │ + │ 23 │RD DATA │ I │ FDD │ FDD. containing clock and │ + │ │ │ │ │ data bits │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ Data Window: Generated by FLL, │ + │ 22 │ DW │ I │ FLL │ and used to sample dats │ + │ │ │ │ │ from FDD │ + ├─────┼────────┼───────┼─────────────────┼──────────────────────────────────┤ + │ │ │ │ │ Write Clock: Write dats rate to │ + │ 21 │ WR CLK │ I │ │ FDD FM = 500 kHZ,MFM=1 │ + │ │ │ │ │ MHz,with a pulse witdh of 250 ms│ + │ │ │ │ │ for both FM and MFM │ + │ │ │ │ │ Must be unabled for all │ + │ │ │ │ │ operations, both Read and Write │ + └─────┴────────┴───────┴─────────────────┴──────────────────────────────────┘ + + + + + + + + + + + + The DIO and RQM bits in the Status Register indicate: + when Data is eady and in which direction data will be transferred on the + Data Bus. + + + + READY + + ═══════╗ NOT╔══════╗ ╔═════════╗ ╔═════╗ ╔═══════╕ + REQUEST ║ ║ ║ ║ ║ ║ ║ ║ │ + FOR ║ RDY║ ║ ║ ║ ║ ║ ║ + MASTER ╚════╣ ╠══╝ ╚════╣ ╚══════╝ │ + (RQM) │ │ │ + │ │ │ │ │ + │ │ │ + │ │ │ │ + │ │ │ │ │ + │ │ │ │ + ═════╗ ╔════╤════╗ ╔══════════════════════════════════════ + _WR ║ ║ │ ║ ║ │ │ │ │ + ╚═╣ ╚═╣ │ │ + │ │ │ │ │ │ │ + ═══════╪════╪══════╪══════════╗ ╔════════╗ ╔══════════════ + │ │ │ │ ║ ║ │ ║ ║ │ │ + _RD ╚═╝ ╚═╝ + │ │ │ │ │ │ │ + │ │ │ + ┌────┬────┬──────┬──┬────┬────┬────┬─────┬────┬─┼───────┐ + │ A │ B │ A │B │ A │ C │ D │ C │ D │B│ A │ + └────┴────┴──────┴──┴────┴────┴────┴─────┴────┴─┴───────┘ + + + + + NOTE : (A) - DATA REGISTER READY TO BE WRITTEN INTO BY PROCESSOR + (B) - DATA REGISTER NOT READY TO BE WRITTEN INTO AT PROCESSOR + (C) - DATA REGISTER READY FOR NEXR DATA BYTE TO BE READ BY THE + PROCESSOR. + (D) - DATA REGISTER NOT READY FOR NEXT DATA BYTE TO BE READ BY + PROCESSOR + + + + + + + Pic. STATUS REGISTER TIMING + + + + + + + + + The 8272 is capable of executing 15 different commands. Each command is + initiated by a multi-byte transfer from the proaessor, and the result after + execution of the command may also be a multi-byte transfer back to the + processor. Because of this multi-byte interchange of information between + the 8272 and the processor, it is convenient to consider each command as + consisting of three phases: + + Command Phase: The FDC receives all information required to perform + a particular operation from the processor. + + Execution Phase: The FDC performs the operation it was instructed + to do. + Result Phase: After completion of the operation, status and other + housekeeping information are made available to the + processor. + + During Command or Result Phases the Main Status Register (described earlier) + must be read by the processor before each byte of information is written into + or read from the Data Register. Bits D6 and D7 in the Main Status Register + must be in a 0 and 1 state, respectively,before each byte of the command word + may be written into the 8272. Many of the commands require multiple bytes, + and as a result the Main Status Register must be read prior to each byte + transfer to the 8272. On the other hand, during the Result Phase, D6 and D7 + in the Main Status Register must both 1's (D6=1 and D7=1) before reading each + byte from the Data Register. Note, this reading of the Main Status Register + before each byte transfer to the 8272 is required in only the Command and + Result Phases, and NOT during the Execution Phase. + + During the Execution Phase, the Main Status Register need not be read. If the + 8272 is in the NON-DMA Mode, then the receipt of each data byte (if 8272 is + reading data from FDD) is indicated by an interrupt signal on pin 18 (INT=1). + The generation of Read signal (_RD=0) will reset the interrupt as well as + output the Data onto the Data Bus. For example, if the processor connot handle + interrupts fast enough (every 13 ms for MFM mode) then it may poll the Main + Status Register and then bit D7 (RQM) functions just like the interrupt signal. + If a Write Command is in process then the _WR signal performs the reset to the + interrupt signal. + If the 8272 is in the DMA Mode, no interrupts are generated during the + Execution Phase. The 8272 generated DRQ's (DMA Requests) when each byte of + data is available. The DMA Controller responds to this request with both a + _DACK =0 (DMA Acknowledge) and a _RD = 0 (Read signal). + When the DMA Acknowlege signal goes low (_DACK=0) then the DMA Request is + reset (DRQ=0). If a Write Command has been prorammed then a _WR signal will + appear instead of _RD. After the Execution Phase has been completed (Terminal + Count has occurred) then an interrupt will occur (INT=1). This signifies the + beginning of the Result Phase. When the first byte of data is read during the + Result Phase, the interrupt is automatically reset (INT=0). + + + It is important to note that during the Result Phase all bytes shown in the + Command Table must be read. The Read Data Command, for example, has seven + bytes of data in the Result Phase. All seven bytes must be read in order to + succesfully complete the Read Data Command. The 8272 will not accept a new + command until all seven bytes have been read. Other commands may require fewer + bytes to be read during the Result Phase. + + The 8272 contains five Status Register. The Main Status Register mentioned + above may be read by the processor at any time. The other four Status + Registers (ST0,ST1,ST2, and ST3) are only available during the Result Phase, + and may be read only after successfully completing command. The particular + command which has been executed determines how many of the Status Register + will be read. + + The bytes of data which are sent to the 8272 in the Result Phase, must occur + in the order shown in the Command Table. That is ,the Command Code must be + sent first and the other bytes sent in the prescribed sequence. + No foreshortening of the Command of Result Phases are allowed. After the last + byte of data in the Command Phase is sent to the 8272 the Execution Phase + automatically starts. In a similar fashion, when the last byte of data is read + out in the Result Phase, the command is automtically ended and the 8272 is + ready for a new command. Acommand may be aborted by simply sending a Terminal + Count to pin 16 (TC=1). This is convenient means of ensuring that the + processor may always get the 8272's attention even if the disk system hangs + up in an abnormal manner. + + POLLING FEATURE OF THE 8272 + + After the Specify command has been sent to the 8272, the Drive Select Lines + DS0 and DS1 will automatically go into a polling mode. In between commands + (and between step pulses in the SEEK command) the 8272 polls all four FDD + looking for a change in the Ready line from any of the drives. If the Ready + line changes state (usually due to a door opening of closing) then the 8272 + will generate an interrupt. When Status Register 0 (ST0) is read (after Sense + interrupt Status is issued), Not Ready (NR) will be indicated. The polling of + the Ready line by the 8272 occurs continuously between instructions, thus + notifying the processor which drives are on or off line. + + + + + + + + + + + + TABLE 1. 8272 COMMAND SET + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ READ DATA │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ MT MFM SK 0 0 1 1 0 │Command Codes │ + │ │ W │ 0 0 0 0 0 HDS DS1 DS0│ │ + │ │ W │ │ │ + │ │ W │-------------C-------------------│Sector ID information │ + │ │ W │-------------H-------------------│prior to Command │ + │ │ W │-------------R-------------------│execution │ + │ │ W │-------------N-------------------│ │ + │ │ W │------------EOT------------------│ │ + │ │ W │------------GPL------------------│ │ + │ │ W │------------DTL------------------│ │ + │ │ │ │ │ + │Execution│ │ │Data transfer │ + │ │ │ │between the FDD │ + │ │ │ │and the main - system │ + │ │ │ │ │ + │ │ │ │ │ + │Result │ R │------------ST0------------------│Status information │ + │ │ R │------------ST1------------------│after Command │ + │ │ R │------------ST2------------------│execution │ + │ │ R │-------------C-------------------│ │ + │ │ R │-------------H-------------------│Sector ID information │ + │ │ R │-------------R-------------------│after command │ + │ │ R │-------------N-------------------│execution │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + + + + + + + + + + + + + + + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ READ DELETED DATA │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ MT MFM SK 0 1 1 0 0 │Command Codes │ + │ │ W │ 0 0 0 0 0 HDS DS1 DS0│ │ + │ │ W │ │ │ + │ │ W │-------------C-------------------│Sector ID information │ + │ │ W │-------------H-------------------│prior to Command │ + │ │ W │-------------R-------------------│execution │ + │ │ W │-------------N-------------------│ │ + │ │ W │------------EOT------------------│ │ + │ │ W │------------GPL------------------│ │ + │ │ W │------------DTL------------------│ │ + │ │ │ │ │ + │Execution│ │ │Data transfer │ + │ │ │ │between the FDD │ + │ │ │ │and the main - system │ + │ │ │ │ │ + │ │ │ │ │ + │Result │ R │------------ST0------------------│Status information │ + │ │ R │------------ST1------------------│after Command │ + │ │ R │------------ST2------------------│execution │ + │ │ R │-------------C-------------------│ │ + │ │ R │-------------H-------------------│Sector ID information │ + │ │ R │-------------R-------------------│after command │ + │ │ R │-------------N-------------------│execution │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + + + + + + + + + + + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ WRITE DATA │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ MT MFM 0 0 0 1 0 1 │Command Codes │ + │ │ W │ 0 0 0 0 0 HDS DS1 DS0│ │ + │ │ W │ │ │ + │ │ W │-------------C-------------------│Sector ID information │ + │ │ W │-------------H-------------------│prior to Command │ + │ │ W │-------------R-------------------│execution │ + │ │ W │-------------N-------------------│ │ + │ │ W │------------EOT------------------│ │ + │ │ W │------------GPL------------------│ │ + │ │ W │------------DTL------------------│ │ + │ │ │ │ │ + │Execution│ │ │Data transfer │ + │ │ │ │between the FDD │ + │ │ │ │and the main - system │ + │ │ │ │ │ + │ │ │ │ │ + │Result │ R │------------ST0------------------│Status information │ + │ │ R │------------ST1------------------│after Command │ + │ │ R │------------ST2------------------│execution │ + │ │ R │-------------C-------------------│ │ + │ │ R │-------------H-------------------│Sector ID information │ + │ │ R │-------------R-------------------│after command │ + │ │ R │-------------N-------------------│execution │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + + + + + + + + + + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ WRITE DELETED DATA │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ MT MFM 0 0 1 0 0 1 │Command Codes │ + │ │ W │ 0 0 0 0 0 HDS DS1 DS0│ │ + │ │ W │ │ │ + │ │ W │-------------C-------------------│Sector ID information │ + │ │ W │-------------H-------------------│prior to Command │ + │ │ W │-------------R-------------------│execution │ + │ │ W │-------------N-------------------│ │ + │ │ W │------------EOT------------------│ │ + │ │ W │------------GPL------------------│ │ + │ │ W │------------DTL------------------│ │ + │ │ │ │ │ + │Execution│ │ │Data transfer │ + │ │ │ │between the FDD │ + │ │ │ │and the main - system │ + │ │ │ │ │ + │ │ │ │ │ + │Result │ R │------------ST0------------------│Status information │ + │ │ R │------------ST1------------------│after Command │ + │ │ R │------------ST2------------------│execution │ + │ │ R │-------------C-------------------│ │ + │ │ R │-------------H-------------------│Sector ID information │ + │ │ R │-------------R-------------------│after command │ + │ │ R │-------------N-------------------│execution │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + + + + + + + + + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ READ TRACK │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ 0 MFM SK 0 0 0 1 0 │Command Codes │ + │ │ W │ 0 0 0 0 0 HDS DS1 DS0│ │ + │ │ W │ │ │ + │ │ W │-------------C-------------------│Sector ID information │ + │ │ W │-------------H-------------------│prior to Command │ + │ │ W │-------------R-------------------│execution │ + │ │ W │-------------N-------------------│ │ + │ │ W │------------EOT------------------│ │ + │ │ W │------------GPL------------------│ │ + │ │ W │------------DTL------------------│ │ + │ │ │ │ │ + │Execution│ │ │Data transfer │ + │ │ │ │between the FDD │ + │ │ │ │and the main - system. │ + │ │ │ │FDC read all of │ + │ │ │ │cylinders contents │ + │ │ │ │from index hole to │ + │ │ │ │EOT │ + │ │ │ │ │ + │ │ │ │ │ + │Result │ R │------------ST0------------------│Status information │ + │ │ R │------------ST1------------------│after Command │ + │ │ R │------------ST2------------------│execution │ + │ │ R │-------------C-------------------│ │ + │ │ R │-------------H-------------------│Sector ID information │ + │ │ R │-------------R-------------------│after command │ + │ │ R │-------------N-------------------│execution │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + + + + + + + + + + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ READ ID │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ 0 MFM 0 0 1 0 1 0 │Command Codes │ + │ │ W │ 0 0 0 0 0 HDS DS1 DS0│ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │Execution│ │ │The first correct ID │ + │ │ │ │information on the │ + │ │ │ │Cylinder is stored in │ + │ │ │ │Data Register │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │Result │ R │------------ST0------------------│Status information │ + │ │ R │------------ST1------------------│after Command │ + │ │ R │------------ST2------------------│execution │ + │ │ R │-------------C-------------------│ │ + │ │ R │-------------H-------------------│Sector ID information │ + │ │ R │-------------R-------------------│during Execution │ + │ │ R │-------------N-------------------│Phase. │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + + + + + + + + + + + + + + + + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ FORMAT A TRACK │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ 0 MFM 0 0 1 1 0 1 │Command Codes │ + │ │ W │ 0 0 0 0 0 HDS DS1 DS0│ │ + │ │ W │-------------N-------------------│Bytes/Sector │ + │ │ W │------------SC-------------------│Sectors/Cylinder │ + │ │ W │------------GPL------------------│Gap 3 │ + │ │ W │-------------D-------------------│Filler byte │ + │ │ │ │FDC formats an │ + │ │ │ │entire cylinder │ + │Execution│ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │Result │ R │------------ST0------------------│Status information │ + │ │ R │------------ST1------------------│after Command │ + │ │ R │------------ST2------------------│execution │ + │ │ R │-------------C-------------------│ │ + │ │ R │-------------H-------------------│In this case, the ID │ + │ │ R │-------------R-------------------│information has no │ + │ │ R │-------------N-------------------│meaning │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + + + + + + + + + + + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ SCAN EQUAL │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ MT MFM SK 1 0 0 0 1 │Command Codes │ + │ │ W │ 0 0 0 0 0 HDS DS1 DS0│ │ + │ │ W │ │ │ + │ │ W │-------------C-------------------│Sector ID information │ + │ │ W │-------------H-------------------│prior to Command │ + │ │ W │-------------R-------------------│execution │ + │ │ W │-------------N-------------------│ │ + │ │ W │------------EOT------------------│ │ + │ │ W │------------GPL------------------│ │ + │ │ W │------------DTL------------------│ │ + │ │ │ │ │ + │Execution│ │ │Data compared │ + │ │ │ │between the FDD │ + │ │ │ │and the main - system. │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │Result │ R │------------ST0------------------│Status information │ + │ │ R │------------ST1------------------│after Command │ + │ │ R │------------ST2------------------│execution │ + │ │ R │-------------C-------------------│ │ + │ │ R │-------------H-------------------│Sector ID information │ + │ │ R │-------------R-------------------│after command │ + │ │ R │-------------N-------------------│execution │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + + + + + + + + + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ SCAN LOW OR EQUAL │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ MT MFM SK 1 1 0 0 1 │Command Codes │ + │ │ W │ 0 0 0 0 0 HDS DS1 DS0│ │ + │ │ W │ │ │ + │ │ W │-------------C-------------------│Sector ID information │ + │ │ W │-------------H-------------------│prior to Command │ + │ │ W │-------------R-------------------│execution │ + │ │ W │-------------N-------------------│ │ + │ │ W │------------EOT------------------│ │ + │ │ W │------------GPL------------------│ │ + │ │ W │------------STP------------------│ │ + │ │ │ │ │ + │Execution│ │ │Data compared │ + │ │ │ │between the FDD │ + │ │ │ │and the main - system. │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │Result │ R │------------ST0------------------│Status information │ + │ │ R │------------ST1------------------│after Command │ + │ │ R │------------ST2------------------│execution │ + │ │ R │-------------C-------------------│ │ + │ │ R │-------------H-------------------│Sector ID information │ + │ │ R │-------------R-------------------│after command │ + │ │ R │-------------N-------------------│execution │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ SCAN HIGH OR EQUAL │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ MT MFM SK 1 1 1 0 1 │Command Codes │ + │ │ W │ 0 0 0 0 0 HDS DS1 DS0│ │ + │ │ W │ │ │ + │ │ W │-------------C-------------------│Sector ID information │ + │ │ W │-------------H-------------------│prior to Command │ + │ │ W │-------------R-------------------│execution │ + │ │ W │-------------N-------------------│ │ + │ │ W │------------EOT------------------│ │ + │ │ W │------------GPL------------------│ │ + │ │ W │------------STP------------------│ │ + │ │ │ │ │ + │Execution│ │ │Data compared │ + │ │ │ │between the FDD │ + │ │ │ │and the main - system. │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │Result │ R │------------ST0------------------│Status information │ + │ │ R │------------ST1------------------│after Command │ + │ │ R │------------ST2------------------│execution │ + │ │ R │-------------C-------------------│ │ + │ │ R │-------------H-------------------│Sector ID information │ + │ │ R │-------------R-------------------│after command │ + │ │ R │-------------N-------------------│execution │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ RECALIBRATE │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ 0 0 0 0 0 1 1 1 │Command Codes │ + │ │ W │ 0 0 0 0 0 0 DS1 DS0│ │ + │ │ │ │ │ + │ │ │ │ │ + │Execution│ │ │Head retracted to │ + │ │ │ │Track 0 │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ SENSE INTERRUPT STATUS │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ 0 0 0 0 1 0 0 0 │Command Codes │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │Result │ R │-------------ST0-----------------│Status information at │ + │ │ R │-------------PCN-----------------│the end of each seek │ + │ │ │ │operation about the │ + │ │ │ │FDC │ + │ │ │ │ │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ SPECIFY │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ 0 0 0 0 0 0 1 1 │Command Codes │ + │ │ │ │ │ + │ │ W │----SRT------------------HUT-----│ │ + │ │ │ │ │ + │ │ W │----HLT------------------------ND│ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ SENSE DRIVE STATUS │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ 0 0 0 0 0 1 0 0 │Command Codes │ + │ │ │ │ │ + │ │ W │ 0 0 0 0 0 HDS DS1 DS0│ │ + │ │ │ │ │ + │Result │ R │------------ST3------------------│ Status information │ + │ │ │ │ about FDD │ + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ SEEK │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ 0 0 0 0 1 1 1 1 │Command Codes │ + │ │ │ │ │ + │ │ W │ 0 0 0 0 0 HDS DS1 DS0│ │ + │ │ │ │ │ + │ │ W │------------NCN------------------│ Status information │ + │ │ │ │ about FDD │ + │Execution│ │ │ │ + │ │ │ │Head is positioned │ + │ │ │ │over proper Cylinder │ + │ │ │ │on Diskette │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + + + ┌─────────┬─────┬─────────────────────────────────┬────────────────────────┐ + │ │ │ DATA BUS │ │ + │ │ ├─────────────────────────────────┤ │ + │PHASE │ R/W │ D7 D6 D5 D4 D3 D2 D1 D0 │REMARKS │ + ├─────────┴─────┴─────────────────────────────────┴────────────────────────┤ + │ INVALID │ + ├─────────┬─────┬─────────────────────────────────┬────────────────────────┤ + │Command │ W │ -------INVALID CODE------------│Invalid Command │ + │ │ │ │Codes (NoOp - FDC │ + │ │ │ │goes into Standby │ + │ │ │ │State) │ + │ │ │ │ │ + │ │ │ │ │ + │Result │ R │------------ST0------------------│ST0=80 HEX. │ + └─────────┴─────┴─────────────────────────────────┴────────────────────────┘ + + + + + + + Note: 1. Symbols used in this table are described at the end of this section. + 2. A0 = 1 for all operations. + 3. X = Don't care, usually made to equal binary 0. + + + + + TABLE 2. COMMAND MNEMONICS + ┌─────────┬─────────────────┬───────────────────────────────────────────────┐ + │ SYMBOL │ NAME │ DESCRIPTION │ + │ │ │ │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ │ │ │ + │ A0 │Addres line 0 │A0 controls selection of Main Status │ + │ │ │ │ + │ │ │Register (A0=0) or Data Register (A0=1) │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ C │Cylinder Number │C stands for the current selected Cylinder │ + │ │ │track number 0 trough 76 of the medium. │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ D │Date │D stands for the data pattern which is │ + │ │ │going to be written into a Sector. │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ D7-D0 │Data Bus │8-bit Data where D7 is the most │ + │ │ │significant bit,and D0 is the least │ + │ │ │significant bit. │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ DS0,DS1 │Drive Select │DS stands for a selected drive number 0 │ + │ │ │or 1. │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ DTL │Date Length │When N is defined as 00,DTL stands for │ + │ │ │the data length which users are going to │ + │ │ │read out or write into the Sector. │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ EOT │ End of Track │EOT stands for the final Sector number of │ + │ │ │a Cylinder. │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ GPL │ Gap Length │GPL stands for the length of Gap 3 │ + │ │ │(spacing between Sector excluding VCO │ + │ │ │Sync.Field). │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ H │ Head Addres │ H stands for head number 0 or 1,as │ + │ │ │ specified in ID field. │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ HDS │ Head Select │ HDS stands for a selected head number 0 │ + │ │ │ or 1 (H=HDS in all command words). │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ HLT │ Head Load Time │ HLT stands for the head load time in the │ + │ │ │ FDD (2 to 254 ms in 2 ms increment). │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ HUT │ Head Unload Time│ HUT stands for the head unload time after │ + │ │ │ a read or write operation has occure (16 │ + │ │ │ to 240 ms in 16 ms increments). │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ │ │ If MF is low, FM mode is selected end if │ + │ MFM │FM or MFM Mode │ it is high, MFM mode is selected │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ MT │Multi-Track │ If MT is high, a multi-track operation is to │ + │ │ │ be performed (a cylinder under both HD0 │ + │ │ │ and HD1 will be read or written). │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ │ │ │ + │ N │ Number │ N stands for the number of data bytes │ + │ │ │ written in a Sector. │ + └─────────┴─────────────────┴───────────────────────────────────────────────┘ + + + + + + + + ┌─────────┬─────────────────┬───────────────────────────────────────────────┐ + │ SYMBOL │ NAME │ DESCRIPTION │ + │ │ │ │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ │ │ │ + │ NCN │New Cylinder │NCN stands for a new Cylinder number, │ + │ │ Number │which is going to be reachad as a result │ + │ │ │of the Seek operation.Desired position of Head.│ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ ND │NON-DMA Mode │ND stands for operation in the NON-DMA Mode │ + │ │ │ │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ PCN │Present Cylinder │PCN stands for the Cylinder number at the │ + │ │ Number. │completion of SENSE INTERRUPT STATUS Command. │ + │ │ │Position of Head at present time. │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ │ │ │ + │ R │Record │It stands for the Sector number, which will │ + │ │ │be read or writen │ + │ │ │ │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ │ │ │ + │ R/W │Read/Write │Read or Write signal │ + │ │ │or 1. │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ SC │Sector │SC indicates the number of Sectors per │ + │ │ │cylinder │ + │ │ │ │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ │ │ │ + │ SK │ Skip │SK stands for Skip Deleted Data Addres Mark │ + │ │ │ │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ │ │ │ + │ SRT │ Step Rate Time │SRT stands for the Stepping Rate for the │ + │ │ │FDD (1 to 16 ms in 1 ms increments).The same │ + │ │ │Stepping Rate applies to all drives (F=1ms │ + │ │ │E=2ms. etc) │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ ST0 │ Status 0 │ST0-3 stand for one of four registers which │ + │ ST1 │ Status 1 │ store the status information after a command │ + │ ST2 │ Status 2 │ has been executed. This information is │ + │ ST3 │ Status 3 │ availaible during the result phase after │ + │ │ │ command execution. These registers should not │ + │ │ │ be cofused with the main status register │ + │ │ │ (selected by A0 = 0). ST0-3 may be read only │ + │ │ │ after a command has been executed and contain │ + │ │ │ information relevant to that particular │ + │ │ │ command. │ + ├─────────┼─────────────────┼───────────────────────────────────────────────┤ + │ │ │ During a Scan operation, if STP=1, the data │ + │ STP │ │ in contiguous sectors is compared byte by byte│ + │ │ │ with data sent from the processor (or DMA), │ + │ │ │ and if STP=2, then alternats sectors are read │ + │ │ │ and compared. │ + └─────────┴─────────────────┴───────────────────────────────────────────────┘ + + + + + + + COMMAND DESCRIPTIONS + + + During the Commnd Phase, the Main Status Register must be polled by the CPU + before each byte is written into the Data Register. The DIO (DB6) and RQM + (DB7) bits in the Main Status Register must be in the "0" and "1" states + respectivety, before each byte of the command may be written into the 8272. + The beginning of the execution phase for any of these commands will chuse + DIO and RQM to switch to "1" and "0" states respectively. + + + READ DATA + + + A set of nine (9) byte words are required to place the FDC into the Read Data + Mode. After the Read Data commands has been issued the FDC loads the head + (if it is in the unloaded state), waits the specified head setting time + (defined in the Specify Command), and begins reading ID Address Mark and ID + fields. When the current sector number ("R") stored in the ID Register (IDR) + compares with the sector number read off the diskette, then FDC outputs data + (from the data field) byte-byte to the main system via the data bus. + + After completion of the read operatipn from the current sector, the Sector + Number is incremented by one , and the data from the next sector is read and + output on the data bus. This continuous read function is called a "Multi- + Sector Read Operation". The Read Data Command may be the receipt of a Terminal + Count signal. Upon receipt of this signal, the FDC stops outputting data to + the processor, but will continue to read data from the current sector, check + CRC (Cyclic Redundancy Count) bytes, and then at the end of the sector + terminate the Read Data Command. + + The amount of data wchich can be hanled with a single command to the FDC + depends upon MT (multo-track), MFM (MFM/FM), and N (Number of Bytes/Sector). + Table 3 below shows the Transfer Capacity. + + + + + TABLE 3. TRANSFER CAPACITY + +┌───────────┬───────┬─────────────┬─────────────────────────────────┬─────────┐ +│Multi-Track│ MFM/FM│ Bytes/Sector│ Maximum Transfer Capacity │ Final │ +│ MT │ MFM │ N │ (Bytes/Sector)(Number of Sectors│ Sector │ +│ │ │ │ │ Read │ +│ │ │ │ │ from │ +│ │ │ │ │ Diskette│ +├───────────┼───────┼─────────────┼─────────────────────────────────┼─────────┤ +│ 0 │ 0 │ 00 │ (128)(26)=3.325 │26 at │ +│ 0 │ 1 │ 01 │ (256)(26)=6.656 │Side 0 or│ +│ │ │ │ │Side 1 │ +├───────────┼───────┼─────────────┼─────────────────────────────────┼─────────┤ +│ │ │ │ │ │ +│ 1 │ 0 │ 00 │ (128)(52)=6.656 │ 26 │ +│ 1 │ 1 │ 01 │ (256)(52)=13.312 │ at Side1│ +├───────────┼───────┼─────────────┼─────────────────────────────────┼─────────┤ +│ │ │ │ │Side 1 │ +│ 0 │ 0 │ 01 │ (256)(15)=3.840 │ or 0 │ +│ 0 │ 1 │ 02 │ (512)(15)=7.680 │ 15 │ +├───────────┼───────┼─────────────┼─────────────────────────────────┼─────────┤ +│ │ │ │ │ 15 │ +│ 1 │ 0 │ 01 │ (256)(30)=7.680 │ at │ +│ 1 │ 1 │ 02 │ (512)(30)=15.360 │Side 1 │ +├───────────┼───────┼─────────────┼─────────────────────────────────┼─────────┤ +│ │ │ │ │8 at Side│ +│ 0 │ 0 │ 02 │ (512)(8)=4.095 │0 or 8 at│ +│ 0 │ 1 │ 03 │ (1024)(8)=8.192 │Side 1 │ +├───────────┼───────┼─────────────┼─────────────────────────────────┼─────────┤ +│ │ │ │ │ │ +│ 1 │ 0 │ 02 │ (512)(16)=8.192 │8 at │ +│ 1 │ 1 │ 03 │ (1024)(16)=16.384 │Side 1 │ +│ │ │ │ │ │ +└───────────┴───────┴─────────────┴─────────────────────────────────┴─────────┘ + + + + + + The "multi-track" function (MT) allows the FDC to read data from sides of the + diskette. For a particular cylinder, data will be transferred starting at + Sector 1,Side 0 and completing at Sector L, Side 1 ( Sector L- last sector + on the side). Note, this function pertains to only one cylinder (the same + track ) on each side of the diskette. + + When N=0, then DTL defines the length which the FDC must treat as a sector. + If DTL is smaller than the actual data length in a Sector, the data beyong DTL + in the Sector, is not sent to the Data Bus. The FDC reads (internally) the + complete Sector performing the CRC check, and depending upon the manner of + command termination, may perform a Multi-Sector Read Operation. When N is + no-zero, then DTL has no meaning and should be set to 0FFH. + + At the completion of the Read Data Command, the head is not unloaded until + after Head Unload Time inteval (specified in the Specify Command) has elapsed. + If the processor issues another command before the head unloads then the head + setting time may be saved between subsequent reads. This time out is + particulary valuable when a diskette is copied from one drive to another. + + + If the FDC detects the Index Hole twice without finding the riht sector, + (indicated in "R"), then the FDC sets the ND (No Data) flag in Status Register + 1 to a 1 (high), and terminates the Read Data Command. (Status Register 0 also + has bits 7 and 6 set to 0 and 1 respectively). + + After reading the ID and Data Fields in each sector, the FDC checks the CRC + bytes . If a read error is detected (incorrect CRC in ID field), the FDC sets + the DE (Data Error) flag in Status Register 1 to a 1 (high), and if a CRC + error occurs in the Data Field the FDC also sets the DD(Data Error in Data + Field) flag in Status Register 2 to a 1 (high), and terminates the Read Data + Command. (Status Register 0 also has bits 7 and 6 set to 0 and 1 respectively) + + + If the FDC reads a Deleted Data Address Mark off the diskette, and the SK bit + (bit D5) in the first Command Word) is not set (SK=0), then the FDC sets the + CM (Control Mark) flag in Status Register 2 to a 1 (high), and terminates the + Read Data Command,after reading all the data in the Sector. If SK=1, the FDC + skips the sector with the Deleted Data Address Mark and reads the next sector. + + During disk data transfers between the FDC and the processor, via data bus, + FDC must be serviced by the processor every 27 ms in the FM Mode, and every + 13 ms in the MFM Mode, or the FDC sets the OR (Over Run) flag in Status + Register 1 to a 1 (high), and terminates the Read Data Command. + + If the processor terminates a read (or write) operation in the FDC, then the + ID information in the Result Phase is dependent upon the state of the MT bit + and EOT byte. Table 4 shows the values for C,H,R, and N, when the processor + terminates the Command. + + + + + TABLE 4. ID INFORMATION WHEN PROCESSOR TERMINATES COMMAND + +┌────┬─────┬──────────────────────────┬──────────────────────────────────┐ +│ MT │ EOT │ Final Sector Transferred │ ID information at Result Phase │ +│ │ │ Processor ├────────┬────────┬───────┬────────┤ +│ │ │ │ C │ H │ R │ N │ +├────┼─────┼──────────────────────────┼────────┼────────┼───────┼────────┤ +│ │ 1A │Sector 1 to 25 at Side 0 │ NC │ NC │ R+1 │ NC │ +│ │ │ │ │ │ │ │ +│ │ 0F │Sector 1 to 14 at Side 0 │ │ │ │ │ +│ │ │ │ │ │ │ │ +│ │ 08 │Sector 1 to 7 at Side 0 │ │ │ │ │ +│ ├─────┼──────────────────────────┼────────┼────────┼───────┼────────┤ +│ │ 1A │Sector 26 at Side 0 │ │ │ │ │ +│ │ 0F │Sector 15 at Side 0 │ C+1 │ NC │ R=01 │ NC │ +│ │ 08 │Sector 8 at Side 0 │ │ │ │ │ +│ 0 ├─────┼──────────────────────────┼────────┼────────┼───────┼────────┤ +│ │ │ │ │ │ │ │ +│ │ 1A │Sector 1 to 25 at Side 1 │ │ │ │ │ +│ │ 0F │Sector 1 to 14 at Side 1 │ │ │ │ │ +│ │ 08 │Sector 1 to 7 at Side 1 │ NC │ NC │ R+1 │ NC │ +│ ├─────┼──────────────────────────┼────────┼────────┼───────┼────────┤ +│ │ │ │ │ │ │ │ +│ │ 1A │Sector 26 at Side 1 │ │ │ │ │ +│ │ 0F │Sector 15 at Side 1 │ C+1 │ NC │ R=01 │ NC │ +│ │ 08 │SEctor 8 at Side 1 │ │ │ │ │ +│ │ │ │ │ │ │ │ +├────┼─────┼──────────────────────────┼────────┼────────┼───────┼────────┤ +│ │ 1A │Sector 1 to 25 at Side 0 │ NC │ NC │ R+1 │ NC │ +│ │ │ │ │ │ │ │ +│ │ 0F │Sector 1 to 14 at Side 0 │ │ │ │ │ +│ │ │ │ │ │ │ │ +│ │ 08 │Sector 1 to 7 at Side 0 │ │ │ │ │ +│ ├─────┼──────────────────────────┼────────┼────────┼───────┼────────┤ +│ │ 1A │Sector 26 at Side 0 │ │ │ │ │ +│ │ 0F │Sector 15 at Side 0 │ NC │ LSB │ R=01 │ NC │ +│ │ 08 │Sector 8 at Side 0 │ │ │ │ │ +│ 1 ├─────┼──────────────────────────┼────────┼────────┼───────┼────────┤ +│ │ │ │ │ │ │ │ +│ │ 1A │Sector 1 to 25 at Side 1 │ │ │ │ │ +│ │ 0F │Sector 1 to 14 at Side 1 │ │ │ │ │ +│ │ 08 │Sector 1 to 7 at Side 1 │ NC │ NC │ R+1 │ NC │ +│ ├─────┼──────────────────────────┼────────┼────────┼───────┼────────┤ +│ │ │ │ │ │ │ │ +│ │ 1A │Sector 26 at Side 1 │ │ │ │ │ +│ │ 0F │Sector 15 at Side 1 │ C+1 │ LSB │ R=01 │ NC │ +│ │ 08 │SEctor 8 at Side 1 │ │ │ │ │ +│ │ │ │ │ │ │ │ +└────┴─────┴──────────────────────────┴────────┴────────┴───────┴────────┘ + + + + + Note : 1. NC (No Change); The same valua as the one at the beginning of + command execution. + + 2. LSB (Least Significant Bit); The least significant bit of H is + completed + + + + + + + + + + WRITE DATA + + + A set of nine (9) bytes are required to set the FDC into the Write Data mode. + After the Write Data command has been issued the FDC loads the head (if it + is in the unloaded stste),waits the specified head setting time ( defined + in the Specify Command), and begins reading ID Fields. When the current number + ("R"), stored in the ID Register (IDR) compares with the sector number read + off the diskette, then the FDC takes data from the processor byte-by-byte via + the data bus, and outputs it to the FDD. + + After writing data into the current sector, the Sector Number stored in "R" is + incremented by one, and the next data field is written into. The FDC continues + this "Multi-Sector Write Operation" until the issuance of a Terminal Count + signal. If a Terminal Count signal is sent to the FDC it continues writing + into the current sector to complete the data field. If the Terminal Count + signal is received while a data field is being written then the remainder of + the data field is filled with 00 (zeros). + + The FDC reads the ID fields of each sector and checks the CRC bytes. If the + FDC detects a read error (incorrect CRC) in one of the ID Fields, it sets the + DE (Data Error) flag of Status Register 1 to a 1 (high), and terminates the + Write Data Command. (Status Register 0 also has bits 7 and 6 set to 0 and 1 + respectively.) + + + The Write Command operates in much the same manner as Read Command. The + following items are the same; refer to the Read Data Command for details; + + + + ▐ Transfer Capacity + + ▐ EN (end of Cylinder) Flag + + ▐ ND (No Data) Flag + + ▐ Head Unload Time Interval + + ▐ ID Information when the processor terminates + command (see Table 2) + ▐ Definition of DTL when N=0 and when N!=0 + + In the Write Data mode, data transfers between the processor and FDC must + occur every 31 ms in the FM mode, and every 15 ms in the MFM mode. If the + time interval between data transfers is longer than this then the FDC sets the + OR (Over Run) flag in Status Register 1 to a 1 (high), and terminates the + Write Data Command. + + + + WRITE DELETED DATA + + This command is the same as the Write Data Command except a Deleted Data + Address Mark is written at the beginning of the Data Field instead of the + normal Data Address Mark. + + + READ DELETED DATA + + + This command is the same as Read Data Command except that when the FDC + detects a Data Address Mark at the beginnin of a Data Field ( and SK = 0 + (low)), it will read all the data in the sector and set the CM flag in Status + Register 2 to a 1 (high), and then terminate the command . If SK=1, then the + FDC skips the sector with the Data Address Mark and reads the next sector. + + + READ A TRACK + + + This command is similar to READ DATA Command except that the entire data + field is read continuously from each of the sectors of a track. Immediately + after encountering the INDEX HOLE, the FDC starts reading all data fields on + the track as continuous blocks of data. If the FDC finds an error in the ID + or DATA CRC check bytes, it continues to read data from the track. The FDC + compares the ID information read from each sector with the valua stored in the + IDR, and sets the ND flag of Status Register 1 to 1 (high) if there is no + comparison. Multi-track or skip operations are not allowed with this command. + + This command terminates when EOT number of sectors have been read. If the FDC + does not find an ID Address Mark on the diskette after it encountera the INDEX + HOLE for the second time, then it sets the MA (missing address mark) flag in + Status Register 1 to 1 (high), and terminates the command. (Status Register 0 + has bits 7 and 6 set to 0 and 1 respectively.) + + + READ ID + + + The Read ID Command is used to give the present position of the recording + head. The FDC stores the values from the first ID Field it is able to read. + If no proper ID Address Mark is found on the diskette, before the INDEX HOLE + is encountered for the second time then the MA (Missing Address Mark) flag in + Status Register 1 is set to 1 (high), and if no data is found then ND (No + Data ) flag is also set in Status Register 1 to 1 (high) and the command is + terminated. + + + + + FORMAT TRACK + + + The Format Command allows an entire track to be formatted. After the INDEX + HOLE is detected, Data is written on the Diskette:Gaps,Address Marks,ID Fields + and Data Fields, all per the IBM System 34 (Double Density) or System 3740 + (Single Density) Format are recorded. The particular format which will be + written is controlled by the values programmed into N (number of bytes/sector), + SC (sector/cylinder), GPL (Gap Length), and D (Data Pattern) which are + supplied by the processor during the Command Phase. The Data Field is filled + with the Command Phase. The Data Field is filled with the Byte of data stored + in D. The ID Field for each sector is supplied by the processor; that is, four + data requests per sector are made by the FDC for C (Cylinder Number), H (Head + Number), R(Sector Number) and N (Number of Bytes/Sector). This allows the + diskette to be formatted with nonsequential sector numbers, if desired. + + After formatting each sector, the processor must send new values for C,H,R, + and N to the 8272 foe each sector on the track. The contents of the R register + is incremented by one after each sector is formatted, thus, the R register + contains a value of R+1 when it is read during the Result Phase. This + incrementing and formatting continues for the whole track until the FDC + encounters the INDEX HOLE for the second time , where-upon it terminates the + command. + + If a FAULT signal is recelved from the FDD at the end of a write operation, + then the FDC sts the EC flag of Status Register 0 to a 1 (high), and + terminates the command after setting bits 7 and 6 of Status Register 0 to 0 + and 1 respectively. Also the loss of a READY signal at the beginnig of a + command execution phase causes command termination. + + Table 5 shows the relationship between N,SC, and GPL for various sector sizes: + + + TABLE 5. SECTOR SIZE RELATIONSHIPS + + ┌──────────┬─────────────────┬─────┬─────┬──────┬────────┬────────────────┐ + │ FORMAT │ SECTOR SIZE │ N │ SC │ GPL1│ GPL2 │ REMARKS │ + ├──────────┼─────────────────┼─────┼─────┼──────┼────────┼────────────────┤ + │ │128 bytes/Sector │ 00 │ 1A │ 07 │ 1B │ IBM Diskette 1 │ + │ FM Mode │256 │ 01 │ 0F │ 0E │ 2A │ IBM Diskette 2 │ + │ │512 │ 02 │ 08 │ 1B │ 3A │ │ + ├──────────┼─────────────────┼─────┼─────┼──────┼────────┼────────────────┤ + │ │1024 bytes/Sector│ 03 │ 04 │ __ │ __ │ │ + │ FM Mode │2048 │ 04 │ 02 │ __ │ __ │ │ + │ │4096 │ 05 │ 01 │ __ │ __ │ │ + ├──────────┼─────────────────┼─────┼─────┼──────┼────────┼────────────────┤ + │ │256 │ 01 │ 1A │ 0E │ 36H │IBM Diskette 2D │ + │ │512 │ 02 │ 0F │ 1B │ 54H │ │ + │ MFM Mode │1024 │ 03 │ 08 │ 36H │ 74H │IBM Diskette 2D │ + │ │2048 │ 04 │ 04 │ __ │ __ │ │ + │ │4096 │ 05 │ 02 │ __ │ __ │ │ + │ │8192 │ 06 │ 01 │ __ │ __ │ │ + └──────────┴─────────────────┴─────┴─────┴──────┴────────┴────────────────┘ + + + + Note : 1. GPL1 Suggested values of GPL in Read or Write Commands to avoid + splice point between data and ID field of contiguous sections. + + 2 GPL2, Suggested values of GPL in format command. + + + + + SCAN COMMANDS + + + The SCAN Commands allow data which is being read from the diskette to be + compared against data which is being supplied from the main system (Processor + in NON-DMA mode, and DMA Controller in DMA mode). The FDC compares the data + on a byte - by - byte basis, and looks for a sector of data which meets the + conditions of D_FDD = D_Processor,D_FDD<=D_Processor,or D_FDD>=D_Processor. + Ones complement arithmetic is used for comparison (FF=larget number, + 00=smallest number). After a whole sector of data is compared, if the + conditions are not met, the sector number is incremented (R+STP -> R) + and the scan operation is continued.The scan operation continues one of the + following conditions occur: the conditions for scan are met (equal,low,or + high),the last sector on the track is reached (EOT), or the terminal count + signal is received. + + If the conditions for scan are met the FDC sets the SH (Scan Hit) flag of + Status Register 2 to 1 (high), and terminates the Scan Command. If the + conditions for scan are not met between the starting sector (as specified by + R) and the last sector on the cylinder (EOT), then the FDC sets the SN (Scan + Not Satisfied) flag of Status Register 2 to a 1 (high), and terminates the + Scan Command. The receipt of a TERMINAL COUNT signal from the Processor or DMA + Controller during the scan operation will cause the FDC to complete the + comparison of the particular byte which is in process, and then to terminate + the command. Table 6 shows the status of bits SH and SN under various + conditions of SCAN. + + + TABLE 6. SCAN STATUS CODES + ┌─────────────────┬──────────────────────────┬───────────────────────┐ + │ │ STATUS REGISTER 2 │ │ + ├─────────────────┼───────────┬──────────────┤ │ + │ COMMAND │BIT 2 = SN │ BIT 3 = SH │ COMMENTS │ + ├─────────────────┼───────────┼──────────────┼───────────────────────┤ + │ Scan Equal │ 0 │ 1 │D_FDD = D_Processor │ + │ │ 1 │ 0 │D_FDD != D_Processor │ + ├─────────────────┼───────────┼──────────────┼───────────────────────┤ + │ │ 0 │ 1 │D_FDD = D_Processor │ + │Scan Low or Equal│ 0 │ 0 │D_FDD < D_Processor │ + │ │ 1 │ 0 │D_FDD !< D_Processor │ + ├─────────────────┼───────────┼──────────────┼───────────────────────┤ + │ │ 0 │ 1 │D_FDD = D_Processor │ + │Scan High or Equ.│ 0 │ 0 │D_FDD > D_Processor │ + │ │ 1 │ 0 │D_FDD !> D_Processor │ + └─────────────────┴───────────┴──────────────┴───────────────────────┘ + + + + + If the FDC encounters a Deleted Data Address Mark on one of the sectors + (and SK = 0), then it regards the sector as the last sector on the cylinder, + sets CM ( Control Mark) flag of Status Register 2 to a 1 (high) and terminates + the command. If SK = 1, the FDC skips the sector with the Deleted Address + Mark, and reads the next sector. In the second case (SK = 1), the FDC sets the + CM (Contol Mark) flag of Status Register 2 to a 1 (high) in order to show that + a Deleted Sector had been encountered. + + + When either the STP (contiguous sectors STP = 01, or alternate sectors STP=02 + sectors are read) or the MT(Multi-Track) are programmed, it is necessary to + remember that the last sector on the track must be read. For example, if + STP = 02, MT = 0 ,the sectors are numbered sequentially 1 through 26, and we + start the Scan Command at sector 21; the following will happen. + Sectors 21,23, and 25 will be read, then the next sector (26) will be skipped + and the Index Hole will be encountered befor the EOT value of 26 can be read. + This will result in an abnormal termination of the command.If the EOT had been + set at 25 or the scanning started at sector 20, then the Scan Command would be + completed in a normal manner. + + During the Scan Command data is supplied by either the processor or DMA + Controller for comparison against the data read from the diskette. In order to + avoid having the OR (Over Run) flag set in Status Register 1, it is necessary + to have the data available in less than 27 ms (FM Mode) or 13 ms (MFM Mode). + If Overrun occurs the FDC terminates the command. + + + SEEK + + + The read/write head within the FDD is moved from cylinder under control of the + Seek Command. The FDC compares the PCN (Present Cylinder Number) which is the + current head position with the NCN (New Cylinder Number), and performs the + following operation if there is difference: + + PCN < NCN: Direction signal to FDD set to a 1 (high), and Step Pulses are + issued. (Step in.) + + PCN > NCN: Direction signal to FDD set to a 0 (low), and Step Pulses are + issued. (Step Out.) + + + + The rate which Step Pulses are issued is controlled by SRT (Stepping Rate + Time) in the SPECIFY Command. After each Step Pulse is issued NCN is compared + against PCN, and when NCN = PCN, then the SE ( Seek End) flag is set in Status + Register 0 to a 1 (high), and the command is terminated. + + During the Command Phase of the Seek operation the FDC in the FDC BUSY state, + but during the Execution Phase it is in the NON BUSY state. While the FDC is + in the NON BUSY state, another Seek Command may be issued, and in this manner + parallel seek operation may be done on up to 4 Drives at once. + + + If an FDD is in a NOT READY state at the beginnig of the command execution + phase or during the seek operation, then the NR (NOT READY) flag is set in + Status Register 0 to 1 (high), and the command is terminated. + + + + + + RECALIBRATE + + + This command causes the read/write head within the FDD to retract to the + Track 0 position. The FDC clears the contents of the PCN counter, and checks + the status of the Track 0 signal from the FDD. As long as the Track 0 signal + is low, the Direction signal remains 1 (high) and Step Pulses are issued. + When the Track 0 signal goes high, the SE (SEEK END) flag in Status Register 0 + is set to 1 (high) and the command is terminated. If the Track 0 signal is + still low after 77 Stop Pulses have been issued, the FDC sets the SE + (SEEK END) and EC (EQUIPMENT CHECK) flags of Status Register 0 to both 1s + (highs), and terminates the command. + + The abillity to overlap RECALIBRATE Commands to Multiple FDDs, and the loss + of the READY signal, as described in the SEEK Command, also applies to the + RECALIBRATE Command. + + + + SENSE INTERRUPT STATUS + + + + An interrupt signal is generated by the FDC for one of the following reasons: + 1. Upon entering the Result Phase of: + a. Read Data Command + b. Read a Track Command + c. Read ID Command + d. Read Deleted Data Command + e. Write Data Command + f. Format a Cylinder Command + g. Write Deleted Data Command + h. Scan Commands + 2. Ready Line of FDD changes state + 3. End of Seek or Recalibrate Command + 4. During Execution Phase in the NON-DMA Mode + + Interrupts causes by reasons 1 and 4 above occur during normal command + operations and are easilly discernible by the processor. However, interrupts + causes by reasons 2 and 3 above may be uniquely identified with the aid of the + Sense Interrupt Status Command. This command when issued resets the interrupt + signal and via bits 5,6, and 7 of Status Register 0 identifies the cause of + the interrupt. + + + + + TABLE 7. SEEK. INTERRUPT CODES + + ┌─────────────┬───────────────────┬────────────────────────┐ + │ SEEK END │ INTERRUPT CODE │ CAUSE │ + │ ├─────────┬─────────┤ │ + │ BIT 5 │ BIT 6 │ BIT 7 │ │ + ├─────────────┼─────────┼─────────┼────────────────────────┤ + │ 0 │ 1 │ 1 │ Ready Line changed │ + │ │ │ │ state, either polarity │ + ├─────────────┼─────────┼─────────┼────────────────────────┤ + │ │ │ │ Normal Termination │ + │ 1 │ 0 │ 0 │ of Seek or Recalibrate │ + │ │ │ │ Command │ + ├─────────────┼─────────┼─────────┼────────────────────────┤ + │ │ │ │ Abnormal Termination of│ + │ │ │ │ Seek or Recalibrate │ + │ 1 │ 1 │ 0 │ Command │ + │ │ │ │ │ + └─────────────┴─────────┴─────────┴────────────────────────┘ + + + + Neither the Seek or Recalibrate Command have a Result Phase. Therefore, it + is mandatory to use the Sense Interrupt Status Command after these commands + to effectively terminate the and to provide verification of the head position + (PCN). + + + + SPECIFY + + + The Specify Command sets the initial values for each of the three internal + timers. The HUT (Head Unload-Time) defines from the end of the Execution + Phase of one of the Read/Write Commands to the head unload state. This is + programmable from 16 to 240 ms in increments of 16 ms (01 = 16 ms,02 = 32 ms.. + ...OF = 240 ms ). The SRT ( Step Rate Time) defines the time interval between + adjacent step pulses. This timer is programmable from 1 to 16 ms in increments + of 1 ms (F = 1 ms, E = 2ms, etc.). The HLT (Head Load Time) defines the time + between when the Head Load signal goes high and when the Read/Write operation + starts. This timer is programmable from 2 to 254 ms in increments of 2 ms + (01 = 2 ms, 02 = 4 ms, 03 = 6 ms ...FE = 254 ms). + + The time intervals mentioned above are a direct function of the clock (CLK on + pin 19). Times indicated above are for an 8 MHz clock, if the clock was + reduced to 4 MHz (mini-floppy application) then all time intervals are + increased by a factor of 2. + + + The choice of DMA or NON-DMA operation is made by the ND (NON-DMA) bit. + When this bit is high (ND = 1) the NON=DMA mode is selected, and when ND = 0 + the DMA mode is selected. + + + + + SENSE DRIVE STATUS + + + + This command may be used by the processor whenever it wishes to obtain the + status of the FDDs. Status Register 3 contains the Drive Status Information. + + + + INVALID + + + If an invalid command is sent to the FDC ( a command not defined above), then + the FDC will terminate the command. No interrupt is generated by the 8272 + during this condition. Bit 6 and bit 7 (DIO and RQM) in the Main Status + Register are above both high ("1") indicating to the processor that the 8272 + is in the Result Phase and the contents of Status Register 0 (ST0) must be + read. When the processor reads Status Register 0 it will find a 80h indicating + an invalid command was received. + + A Sense Interrupt Status Command must be sent after a Seek or Recalibrate + interrupt, otherwise the FDC will consider the next command to be an invalid + Command. + + In some applications the user may wish to use this command as a No-Op command, + to place the FDC in a standby or no operation state. + + + + + + TABLE 8. STATUS REGISTERS + + ┌─────────────────────────────┬────────────────────────────────────────┐ + │ │ │ + │ BIT │ │ + ├───┬────────────┬────────────┤ DESCRIPTION │ + │NO │ NAME │ SYMBOL │ │ + ├───┴────────────┴────────────┴────────────────────────────────────────┤ + │ STATUS REGISTER 0 │ + ├───┬────────────┬────────────┬────────────────────────────────────────┤ + │D7 │Interrupt │ IC │ D7 = 0 and D6 = 0 │ + │ │Code │ │ Normal Termination of Command, │ + │ │ │ │ (NT) Command was completed and │ + │ │ │ │ properly executind. │ + │ │ │ ├────────────────────────────────────────┤ + │ │ │ │D7=0 and D6 = 1 │ + │D6 │ │ │Abnormal Tremination of Command, │ + │ │ │ │(AT). Execution of Command │ + │ │ │ │was started, but was not │ + │ │ │ │successfully completed. │ + │ │ │ ├────────────────────────────────────────┤ + │ │ │ │ D7 = 1 and D6 = 0 │ + │ │ │ │ Invalid Command issued. (IC). │ + │ │ │ │ Command which was issued was │ + │ │ │ │ never started. │ + │ │ │ ├────────────────────────────────────────┤ + │ │ │ │ D7 = 1 and D6 = 1 │ + │ │ │ │ Abnormal Termination because │ + │ │ │ │ during command execution the │ + │ │ │ │ ready signal from FDD changed │ + │ │ │ │ state. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │ │ │ │ When the FDC completes the │ + │D5 │ Seek End │ SE │ SEEK Command, this flag is set to 1 │ + │ │ │ │ (high). │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D4 │ Equipment │ EC │ If fault Signal is received from the │ + │ │ Check │ │ FDD, or if the Track 0 Signal fails to │ + │ │ │ │ occur after 77 Step Pulses (Recalibrate│ + │ │ │ │ Command) then this flag is set. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D3 │ Not Ready │ NR │ When the FDD is in the not-ready │ + │ │ │ │ state and a read or write command is │ + │ │ │ │ issued. This flag is set.If a read or │ + │ │ │ │ write command is issued to Side 1 │ + │ │ │ │ of single sided drive,then this flag │ + │ │ │ │ is set. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D2 │ Head │ │ This flag is used to indicate the │ + │ │ Address │ HD │ state of the head at interrupt │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │ │ Unit │ │ │ + │D1 │ Select 1 │ US1 │ These flags are used to indicate a │ + ├───┼────────────┼────────────┤ Drive Unit Number at interrupt │ + │D0 │ U.Select 0 │ US0 │ │ + └───┴────────────┴────────────┴────────────────────────────────────────┘ + + + ┌─────────────────────────────┬────────────────────────────────────────┐ + │ │ │ + │ BIT │ │ + ├───┬────────────┬────────────┤ DESCRIPTION │ + │NO │ NAME │ SYMBOL │ │ + ├───┴────────────┴────────────┴────────────────────────────────────────┤ + │ STATUS REGISTER 1 │ + ├───┬────────────┬────────────┬────────────────────────────────────────┤ + │D7 │End of │ EN │ When the FDC tries to access a │ + │ │Cylinder │ │ Sector beyond the final Sector of a │ + │ │ │ │ Cylinder, this flag is set. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D6 │ │ │Not used. This bit is always 0 (low). │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D5 │Data Error │ DE │When the FDC detects a CRC error │ + │ │ │ │in either the ID field or the data field│ + │ │ │ │this flag is set. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D4 │Over Run │ OR │If the FDC is not serviced by the │ + │ │ │ │main-systems during data transfers, │ + │ │ │ │within a certain time interval, this │ + │ │ │ │flag is set. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D3 │ │ │Not used. This bit is always 0 (low). │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │ │ │ │ During execution of READ DATA, │ + │D2 │ No Date │ ND │ WRITE DELETED DATA or SCAN │ + │ │ │ │ Command, if the FDC cannot find the │ + │ │ │ │ Sector specified in the IDR Register, │ + │ │ │ │ this flag is set. │ + │ │ │ ├────────────────────────────────────────┤ + │ │ │ │ During execution the READ ID Command, │ + │ │ │ │ if the FDC cannot read the ID field │ + │ │ │ │ without an error, then this flag is │ + │ │ │ │ set. │ + │ │ │ ├────────────────────────────────────────┤ + │ │ │ │ During the execution of the READ A │ + │ │ │ │ Cylinder Command, if the starting │ + │ │ │ │ sector cannot be found, then this │ + │ │ │ │ flag is set. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │ │ Not │ │ During execution of WRITE DATA, │ + │D1 │ Writable │ NW │ WRITE DELETED DATA or Format A │ + │ │ │ │ Cylinder Command, if the FDC detects │ + │ │ │ │ a write protect signal from the FDD, │ + │ │ │ │ then this flag is set. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D0 │ Missing │ MA │ If the FDC cannot detect the ID │ + │ │ Address │ │ Address Mark after encountering the │ + │ │ Mark │ │ index hole twice, then this flag is set│ + │ │ │ ├────────────────────────────────────────┤ + │ │ │ │ If the FDC cannot detect the Data │ + │ │ │ │ Address Mark or Deleted Data │ + │ │ │ │ Address Mark,this flag is set. Also at │ + │ │ │ │ the same time, the MD (Missing Address │ + │ │ │ │ Mark in Data Field) of Status Register │ + │ │ │ │ 2 is set. │ + └───┴────────────┴────────────┴────────────────────────────────────────┘ + + + + + + + + ┌─────────────────────────────┬────────────────────────────────────────┐ + │ │ │ + │ BIT │ │ + ├───┬────────────┬────────────┤ DESCRIPTION │ + │NO │ NAME │ SYMBOL │ │ + ├───┴────────────┴────────────┴────────────────────────────────────────┤ + │ STATUS REGISTER 2 │ + ├───┬────────────┬────────────┬────────────────────────────────────────┤ + │D7 │ │ │ Not used. This bit is always 0 (low). │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D6 │ Control │ CM │ During execution the READ DATA or │ + │ │ Mark │ │ SCAN Command, if the FDC encounters │ + │ │ │ │ a Sector which contains a Deleted Data │ + │ │ │ │ Address Mark, this flag is set. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D5 │ Data Error │ DD │If the FDC detects a CRC error in the │ + │ │ in Data │ │data field then this flag is set. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D4 │ Wrong │ WC │This bit is related with the ND bit, │ + │ │ Cylinder │ │and when the contents of C on the │ + │ │ │ │medium is different from that stored │ + │ │ │ │in the IDR, this flag is set. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D3 │ Scan Equel │ SH │ During execution, the SCAN Command, │ + │ │ Hit │ │ if the condition of "equel" is │ + │ │ │ │ satisfied, this flag is set. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │ │ Scan Not │ SN │ During execution the SCAN Command, if │ + │D2 │ Satisfied │ │ the FDC cannot find a Sector on the │ + │ │ │ │ cylinder which meets the condition, │ + │ │ │ │ then this flag is set. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D1 │ Bad │ BC │ This bit is related with the ND bit, │ + │ │ Cylinder │ │ and when the content of C on the │ + │ │ │ │ medium is different from that stored │ + │ │ │ │ in the IDR and the content of C is │ + │ │ │ │ FF, then this flag is set. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D0 │ Missing │ │ When data is read from the medium, │ + │ │ Address │ MD │ if the FDC cannot find a Data Address │ + │ │ Mark in │ │ Mark, then this flag is set. │ + │ │ Data │ │ │ + │ │ Field │ │ │ + └───┴────────────┴────────────┴────────────────────────────────────────┘ + + + + + + + + + ┌─────────────────────────────┬────────────────────────────────────────┐ + │ │ │ + │ BIT │ │ + ├───┬────────────┬────────────┤ DESCRIPTION │ + │NO │ NAME │ SYMBOL │ │ + ├───┴────────────┴────────────┴────────────────────────────────────────┤ + │ STATUS REGISTER 3 │ + ├───┬────────────┬────────────┬────────────────────────────────────────┤ + │D7 │ Fault │ FT │ This bit is used to indicate the status│ + │ │ │ │ of the Fault signal from the FDD │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D6 │ Write │ │ This bit used to indicate the status │ + │ │ Protected │ WP │ of the Write Protected signal from the │ + │ │ │ │ FDD. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D5 │ Ready │ RDY │ This bit used to indicate the status │ + │ │ │ │ of the Ready signal from the FDD │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D4 │ Track 0 │ T0 │ This bit used to indicate the status │ + │ │ │ │ of the Track 0 signal from the FDD │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D3 │ Two Side │ TS │ This bit used to indicate the status │ + │ │ │ │ of the Two Side signal from the FDD. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D2 │ Head │ HD │ This bit used to indicate the status │ + │ │ Address │ │ of Side Select signal to the FDD. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D1 │ Unit │ US1 │ This bit used to indicate the status of│ + │ │ Select 1 │ │ the Unit Select 1 signal to the FDD. │ + ├───┼────────────┼────────────┼────────────────────────────────────────┤ + │D0 │ Unit │ US0 │ This bit used to indicate the status of│ + │ │ Select 0 │ │ the Unit Select 0 signal to the FDD. │ + │ │ │ │ │ + └───┴────────────┴────────────┴────────────────────────────────────────┘ + + + + + + + + + + diff --git a/release/LD-ISDOS.EXE b/release/LD-ISDOS.EXE new file mode 100644 index 0000000000000000000000000000000000000000..163097f6b7d506f0b208774c4a87ffd94d9d8780 GIT binary patch literal 19776 zcmb_^3tSXOws-aPOwTYpL_u`bKx51#iXt$PD2%9#;3GcpjT&@O@D&B`FoU`qVO;JS znO1kRxtqITlf8(!dvn#Bj~J5$vn!8L1PKxG?$zLK)-}d78KXucAkO3aSN9Ce`1tns z`+k??-(7u9)u~gbPSvTZ?s5LA>CE%wH71v2X|mq8Yshp$G-^Ud5kkfS!AOS#KLS#K zY+yTJ0e%L&0sIH>5%4*15x5H622>hCVt_F~A}|+N2>cYV0tbLYz)|1};445KM95%Z z5-<(O0X70DT08?Yfn~rdU@fp6umC>+1mKszuYvc0{{sF1v;iH!B|rqe1MUKBFxm=) z0@1*;zze_>APq1AOM#WZ8lVs`1G@kl@C)EyfPV*$0RIQ52hITJfGfaN;A@~8cnFXX zv=4{^Mgrr3L?9WM1ZyMdnp`++xs-vI9dzXy&2jX(?VXFvpQ13v%{fT%D+l7JaN zCXfZJ0A2xdfh|BGa0sXY{sf!@t^#)fClEA1Ly`65rhl@qJd|D7k~ob9pEHT2b>1}2HXH{1KLPJh5=)Mxxi9j z4Ui9P0SbYi1HS;?1}cGn2aW)r0`)-bP}l&N1f&5=fNUTK_$goo%7KHxzX9(7{|TG~ z>VVV0XTWfh!^8oZOb)Xj=m7qz%wc{2+(57@hZzG*1(pMaz&_v*a1!VMz6BIq4l@Es z0^R_Q0F6K=a2NQPv@u@*UjjFQ5T=cp1uO+RfnFe3(Z-|#CxI`3Z-5>kh;3s=0uz8~ zz#wgd9L3ZSa+t|mgzp(!``xG zDzml_{Ksrzw**z>C~_EUT6a3JXpmuFrpFO%EpfA!&zrdJbdWqPjS9$O$o`85?fb7d z51ewl&lD?<9eE?+yL;~)yn-qgT2C>aM2iy1ESgM`l8b0kFC`b#{a#&4nhuI59qP63;Kr&&}Ih zu#w-qWWvmaOZW|23%76I#pi7)P@Yp>?-;td-%Z_Q8R4M-QICG!(_N}QOtfH#|V@#aFlXj9=1KF_jkJ72f~ zwA}Tt@(KJVv>mr1*aik!5XbZUItFP1u4GGo^^BC9@jNvqUqG9>G2dLoZ!i^ZlUzcg1!e5a-L`#e zeo@NYfX4esRon;;vT`Vl`PMJiXs=N9oZL0CWq@7QeKbeeCgx4?YX7wA z1C1bgrPl|i1WJS7O*AF_e@jc8>Mi=jTW&!fp9Ig7yz>c8STrJ_WfM2SEYxi_obk4&MCwYgxkd2{a8%|F3B5+5HQo;lMf(fE9m3HetuIg0W8u*4#>Z=^}y?qw?J zycI$%A~{J4zgoe+5ciJ;6RlPrcX@oq5+gKQpIfj#f9rTYw_ukv_CYBuFmEofqSE;I&>Vj0;u*%5m+v+<{ZJ?Kp{KC3XOxTLLTYU72O&(GatyQy4 z-0jh-ChpE?WcZ$5?$XN-qnV1LcA(ll4P7!z13S2!=E4DBduYr!5+L*dqu>*3X zhq~t>zT!T_S|AfO%hYj!)PB*WY}YTy|GM-5fr_W7YfZZyJJCEu*3aJ_QnSl5-8BqJ z&2*QrU7sS)MLO(JH=*AK!>P3y+9z33 z9#QD2+Q@gUWS&?qp}$<1oI6L#9rxti`bTsBYfshf(OoWBnJWE=PRaebHMH}Yu0KCH z-xOayGuw4sauKYfZpE^e5Nq1^v5B;=;V^!rB$=e}Bk5%l>qmM~CMo?$lVp<0kCZHv zI6u-$GD+=6nk*@9w zaMFM5Qx>-Cghm$l%YnKo*YOG0RWk_oLlr;e;Ozf8z#EW`Tv=P#ic!9el6jdVNUpT* z7>ZOVF`3~Rp`fxmJ*%P>Ti=Q@I>G&ka%t)@FQ!r}-o<{o;#atIMakMdBE(y&u5Lgt zxmsFU9CbIVq6E9+$7Ea65V$L*(FqNoM+V zq1XDS`=fdD6tBr>g!D6+H;?V-_eW<{@WGgPB-8oF(XzBWUSs({iqTTEmc!}uvbm%Q zyuyOLeqE=}-T~oU?)bkA7*U?`<+*N4j<@$K+`dWACl)J$ibL4`KS9_{e__by?Sn02 zeZu-@P(%ZChS$+=4-^}4Fl!o?7x2(ijIX;Ye;5sy^X|_7ALAggzCR2%aa}x&?#8XM z3vNAKxO3qua|a%xcvF#8k%_CH+sZAJG79bJfQGBe>1?CWOFJRqdSb`otct5RQ>jSB z0fo=K`pqNDSLunr@W*A*PLC;`DAoEnSL$w`vHC?jhD+JE#6QNdrgiay;M31|q#Og* zqrO2I54>UQ=@UlXNbU)9P{l&_O-0qc(blwkqeog&ACWFS))}5u@R1R`RQbfBnFB>D zH`0E2doi7E$`NJj77p+R+T&RFL^-Pl@>Xtu9NI@dIk|qkN9)KN;0@FvO%N8oZWBCL za_)*#R3G|?wX8zp4gOFV2STVWCDT*Pb`58%y0GYzTnzIM`ZTNJBTQaR+_$ppearig zeE}WQ^z&St^ddnbEsiG6!85eHgRhthqigEXZ8?fc2VZrQx28FG6)jwU*Uun5o zd3*G}Om{VtlIeyu&XX!pvWDo_nvvxlxyU94_>y+fnYQT{gCXT%5dHRAg_!oZ(&BJ!L05e>?Tjk@Ay)XCM^{Q z#_klU5sw!Aov%RM(~C-WFb{gf@lm~jpuwDFqJI}rzq0-M{^&=#YTvJOWlvLDzL1;= zje651d-_P()7KGf%}8WoeO6Y5!{_AIv~PI^d8fI2PN|co1j9(nGqNKd^K+X1X&ol* zqT>Q3zjMm943cW8_=!)l)HD4dUY1qwC#&CbGRy79>aV6HvA!Y-r@T1NB@FQtbDm=5 z7P>veT7&LZYlr$)9;Zt*T>l2PrI8+{;^kJRGU2+=d*K`5*9tsv3D=)(463gtW@b7@ zw)Zr2S^3w|XO@TTzfykrL*>P*O#3@$N|fa)JcV2o-z{RMpDEFlt72LjLrAj{FFrDz zR$Sb89q%PYVV)K{RZZek3S_pc zttB2}8CO=~B*kMq3!IqQ=y-|FN~}M4xtmK9)8;_;5%mUHMPs&}Sm5YFjCn=)NY6U?!N75{~v*VCCqDYT<~3D<)gv&2#m zT?yAOT%|OpOncQWRbNf0Ce=!MrPYOr2J|nzuk+qlN%t+0Vd4faWws|wEQO{}0xxXq zx<^N^I8frmX1=5^YK8cX3+3TG?KM^+oV$3nJhQj2n!BN`&b$!<1fx@)^N<@#+#5s< zy*ugi9wD=LHchB#f^t;ViW}O8TQbFZNDR*sYjF$95|85+GKR?#{}TyqmRN-w%=BB_ zV8nl+PX@-q!8T!zWP?IVjdYARuu^K8W3)jjrQUW7H>jjkvm*?X1ufC+pl>6_!EjmP zT-O$lnBfxt>Jn|Ps@`<*pIucC(!~;2RbRTe(^d5_T{O9>oay3LSCuPW+~BHmr*Bb; z5l{fihPcF~t}0Ku0|0O^;oOzm3&PL0_Jq_O($ZR4AvL`tx#9UWI6s*;JHLOzvlEB(_o<(@#-XdXR?^hxAjFE$2c= z(6WM83kr7>@Gmf96$@VuOV7>YjX2vg6>i;{Z_+H?jMLp6&{B{Wy27;CoX=;O z3e7nA3-xIs)u3HglyBnG=@DNuQP3%jp1q96j?r%~AWcy;(2Ii}%JC+dW}q8_fcXvi z48$_DZZfz5jILk?PBXMF^)bd>0v{S$H}^5d7X&Ufv~I~`jCukO8(O#KF~)xoINZ>> zg2xyK3H&dzuH;dMqu8JZz5Fry8btHRx;G!AXBvV)fA2ARyg>{4@yF;K~=k zNoer0g8ZHIT~>Y`J&WF!YYv%|kifsXZekJtLc-V(eg8w^*pQ@2K2Fluki?`(-fa4@ znBeLrBR~ZhTkeI(y19=s9GU2Z$hsAe(c{qvk#%%U8X(9Kg)SIU_fL<~ss6sdW~FlA z9VGFbDdq;=LGE?Ch;1+N?Az;fVSR=x7HG|6-(HU!>rGsn_PS^e4`x*CMn5H<8Ky!0 zkE@EK{U7U1k^Yb8cc`cU-k;VUnB{MBmaGG(oDZebP@IW+{o08c)rR79D)mXQl@Uzo zSR4*)c(HCm8Q%#s%}CpU!BeaeGP$@+ z&Gank)b(^pn7wS#mzaB%|jEt)c514VE}hTi-m|e68P0X(wJv52%f*rNjAdTq~4OYPNiDue&W5HIDQd=$$#P#$$xs){t>f*0VBZr8rOE+-vcE+>XpFFP>2 zd~R+1)a~Lep}xnaGPi53@4s6f=>vofCTaq{CP|uFVUZ;2;?RC^VmS1-k+xos>^yh^J@@D$;!UB02{=7kf zyi9*ycpz_gNFZ;HKQAJXH`kvR8OVFtpEop+H_x9J708?K&l?uVTj0+d z9>`nh&-+mz4-=v!<&;Oq zJ;G5K{R9XT!{ZZpyx)9GKN1?4kDItP_()WG+qPxefm0oHTE3Z%v!#!O zGmU>Z!+!U`sXt1y`f=%cj0$-TLaZRO<`)i}ItH!eJX;X1{)mV)TaI{MqEULcOBXFz zAZivF8Xp2ICdb7vvDro1WOu#T(4N2fnDeMG+>7G?ZYD9*7Qpe3q66AA!inPpmKB+t*jV*V*Tj*+$Ah zVance_Ms1GY0oFlKF=q8ePLpGFG>f*9$7lA5#dSY3r~K503v#&xCfedg+t5K{YHbs zRk}>TzEo(&U0U$eXh>XRT!Y*XzOeG-2;*xxbuO=9+Ayh5m{^JE<8gP5#bU^-;uEq3 zSeV9jmGsF(^N6QL@ut1RP4^;_d-X{orR9RtRdxzXpVtNpScJV@)<;U!uZ^7Q@f1hZ zP11(ZRSkT>XY;P@jFhcnYPg!MEhmZHiJppyNLL8Bl<)o4RsOr1uJX5TxoW_?lGq^} z{MIFWa?>T8y5*`Ei#&^$WDQ7Ixn^y}Gg84jD0mkIe{h}Md&9+$vwKAsAr5UBeJXnk z4`=uGx)N~h##K0V!-bQco(tbFJwn-am+;#gF5yklRWU~rcHKo^-|xNdD$OrP@8AUu zt^!IgG1vfLkks1x#9G*%fiG5 z_vOABG1WtgF?MOW055Qih90O^X5su*{`4Rq5A_s!np1-VHG0_ALQj9h7jP(Rj7A;H z@D?12iadO2DIL{?iRp5pVlzlBttSSFL7YKt)*9Giu7)MzYeZ}!Cp1YO@q3l+^qA7B zNMjXe)Yn%r#;T#lswm_1Dq=jyEhTkZ$tjQLBahBDRhKf={1Eq=>z=p84T_%jo{paX z>Aslc5t@U~1%DpgYGGckeTlq&@vWZk4~H8CJ8oe{p$WGTV{}-|$+b+)$miN(W9(G0 z&Z>KzxSoYqV!Y*KAcDylhP)MnaEDqKr&T_IYbsl#y5%JAEc6 zn6@Z0cY?GZs9Mk;I4+2$sf=05_wSgMV+Ms-tvb%QUBhukZ-Zwk$EZJ4c3h?OUwG*>-P39fR*RK&`3B;a=0<+il`#jZb9G#hLm-ZvM-7C3Nfju3w~#(CD$rz z{`%s{Atd!;(TJXV!sY9^@3R(72zw*9`jZ<*oBc+*?d*+o2)Ld*#(5*R)tWXG{ivZm zh{I(?HPc!-6dnMgw%#%%>3Ulf?%I92p+@a>3*1puxuIcn@|jZQ*$hSXrL!4ID>?9U zD=E(i*`E`3HY5BUcK`e#O&JL!2A1+>t@&^E)8k5^bb{y*osIMbaxwe8p4C5QE12 zq9MYZfVV3%=NLwspEoe(XYrclCBq1FrXke4(7>C{r*@iKb^92j_#2Y?WpTZ5&+*6L zE9RPNjrcmL=Ea{8q;`{+uYK!yFZD}vrOw8n)Z5|~V!U?S@rE^xfy>*d0EbpwKy+uB zP_5Aj#q{;M@(hixJV%=&H8S~hsZuA**XYL1*L?LOs;o6l0lNn4Y$|aSnRTtl!HVw? zvDvAwM*-OSWPlE|#6A>st0UbS+y-Q7f8ws^Sv^F@o{`~l-7l3BIV zeu7Q%bZMCr3fx#G`e5`@B1C187@f!@$37W#~*xWYtQ?C~*mqG>U*mgTzcC?(#U)Vj7{DX9+z*=e6I92}G)@997wxx^;6&Qa4^; zHw#hgNp;vQ2eF+=$8~P?AewGSzZGLo?J=)kw0K1{C!CM_Tqi?U1Rs1UC}#yvFv76^qJz210~f_YUeS-LQKpHfAhw@_mb+5 zoLSDD7||AcV0m>^jIcm^VgV*{c! zVv_1>3FEx`LH7k)!$P5Ff$QFTN1QR3fQK9Hw6ya~@sMM-_M~p16V5xxy3_Lt-hb@$ zq?p;4E#KD|3C@MY=ZXG`gR@SKH>-@PotADa-w-Lqa3XZpD3Rnaam3`D3ny_GQ|%^& zU_T->vtQnOPq=44iRry_KR27`zZ0L25-W*tS`|U?LP^};!8RTqK@N{1EEh=*N0Y-Z zki+B2;TOq4WY-;1ki%HQa4F<}$o?<`qHe~iDT>+%@=Is@u@jTpV#}Y|pP?u_tGsrb zhPe>LD1^C_5lqdq^nQiZjG=cWQ!|Z*zZ%5qtmv$o^@=bYG%dgqx>-?!uh<4?DWKIV zTJ`nsthRnLXvw?pth9c8$LhLc4x4U0f5-cbH)K_>5Ie@0f;=oc&1IK;6SL>+Tg2*| zQpDDIJS$EtZHpCdS{Fny*{fHsTC+AMMt#1foggcsL^D~r+M&jJLf@jlB3b6)VZ01$ z2)3K29^y%Gy?NrndflOLni?5r-!ZJ`@>CLD6n-+C^ju>bOln;!ry(XzcPNrLE(p#0 z?QzkwNtq+OJZvT@kIp2gqtnR#dWefa52umC)5+m^q^5ug%i@-_N+t*s$I0yu6Jzn| zhrdmqi#{_HmZB!Tb7&?B<}!(S?5Fb-;y7|Borp=~)71(wnjFH&n@*}z#AO7z#7X4S zA1g#P&2nO1TWq{dt*tk6;$&iU+_Qg}2hN9D%ta1m()I4|l?hppkZn6{&$68s8Iqla zm?erV$sRLEnP5mUDU@nk`w6Zs)=m^7W1k)K;-uu4CQnI8HB3#LW?5{(cgT20A%E~p z_*^qj@F_3JDm0ll7vk3ikN$*WvVQ!OBtE^+v=yId>+4_V=8@L2w0ZbNA=7$j9_iZd z7Jf)RI8&iZU8cZFK2n#eG7Z85_nM{@w$4!QU|MThNY`w4%_Y*6?p6_nDKzeMQBcq2 zRBkRYfqRa0jdP#WchFdLx>S>VW``2f@X?y;OGoj7>?o2)j~>V{AKeey$dIEoY8JHG zFmmr`?LrdVVF@~x(p;>xHGic!2D`CGuJvNr$6ytLcze23OP4o@21?vH+(U3jWXK5f z#fS_oW`UC*UUFzo9>3&ZPkwaC7u+%wQxOe^Og(Z_&Mu0EiOPQ9>QpU}kIb`_}+op@Eqca;%rkNb4$ls4V7Aq@g%Cs73aJ zNxD6yST$JUb;1sfE_H|292d#pXV_m0H5)w=RhR9~vJ1TBWZYh<;06`Z44s%SIuiks~fH^Wa{1H?7!>!I|)PTlFX zA?!ovz4ziCO3HdghGs2Z4xtAibj_-4=wI&>OFMTBSM#Y#-yz;|TeP~e(h=BFiQA&LE4` z$~IxeArgyQqVuec^m>O~dK&I~LNPh>WQh0n(DT%OFp<_0E;f27-TQ2g(0MQ@&~~h_ za$4oCsUG3@L8@FUEa&Eyu;MniEOD&YhR;cbs0d+&k`~5$W!=6Rp42`IcY2LhT6CVI-vEKf!{G0RS%asDoX z6`ff=x}+<|2LyB~R8j@y(T!kZ3B%}@r-vds-JtKhyivq5%sc#p=mX`Wx zdabuqxcGaIWtxzwMHi2XUZm^ER|?Jemd5rKG--=n8Domkcj$U7N-UlBHwIratI#aR zsMJiYd02TEZ7n4C^XNpa%E6DSsViaGHP>T_ML)_?sWBj)Jtwq7b`44QwlD`F1o`1_ z!5wCmIEOeAP9(I&8nA&Srst#;)5NmO*lLq7QbXkmEkcz~eGmV-t>)727EJKB}!WY81Irn~V4#W1K zRVdbGI&SFe9m?5pnH((Ts}btbcy~-^dkz((e1?X7rfo5EX#MXkij>o^fRvTCy_z{f zclSqNW}mgRXfJF6qPHc|{IKUHQIwT%%x=}$OpfuMQA)>FIL6C@H_XQJw$&}Y%?%S- zoQw9Kec>G{mY!fA!@I~XWWk$Lyjl$tce?3t5260z6;DcDDJ#*ClI43!G#*mAa8C*6 zAtkg*&*N2UXqDOY?9F$|2Jd9?wT@g{8fyEgT$@Y?lB%OC9BHSoZz&J0AyY9Bv0e$S zR(MqMm{goFNOM6DrUFFmRpqLhVC6|QOV`eF=84qdXST(5H(G0cOj+3Iby^~&;ucnn zBQ>eM0@9%X&I8JqMU~GVUY;}JY{n=n4jG~$PdXFOcj#LnPJ!_=!Aeg*ij?|#EbB0? zyu<3iudSpO-#kgHmLhnV{z~d)Gj9cLgqbxu?g|&<+A)s2Qm8n(TCwlxAy#zzPvKEJ z;oYh?UjOp-OXC{4FB`@dZQR?iEX#Jodfh6B`m@>ZR1@px);;Hm)%rkV8f-gl`^xq= zTc7QJlDe&38ppQ~qrLF$g)0{>yIU;X@9unwZHV|X;*!voQ>4AnDbX9uybAhXBxM~0 zA2T#qZ5w;9=AemcxruZ3bnUVBo2`hw&^e>~%yf%phOHs#e*1UW?g^KLb~{YqZ9aNP zYBn`PLXq8{fXrVH(_i9cKJ<(KVUU>u|W6cWM_S zyXEWS(;a^o8b9PNUR}LvWeyH^FP7c)K&y6Y_&IwTtk$lLp2hl0t9GdtU+7q6?{2c1 z)!5;iBk$W&8Z2SZNSk`eSE*gN9NcN1WV;pIu}j_4*>f3gEL^Usr2CAJ*DqH8Qrm4& z?!8;RFSui;#@)5TczcXtU9{l4E)bEDU!)fy%?UjBtlD<@2vD@4TJ}2>S ztaRALn@&?|t9Z?6n$(I>dr#;S-*uVBwnFGQ@h!J0rd3pXTEz*T){lv}-eU@C{g@F~ zd+3hqJn5>rQ`1Jej^DwCy6e~-c#-(76R$_?H1&)A)I67umf@x;!}~>Z#xvO zS&OI8R)*NV5jszLJZPrlw%kzfxcdY&4Ri{AK!;cRU(nL~&t7`=%h6xACe^p%^-P%f zK2GAP{@JTni4o3LX$hy1N$4E|ddxBd-$<6P=__CEv^H4VAK+qZ7$1p`#_=hnu%=H~ z?!?kre97Z(hD7o6hxqgw`WF3N9<_9Z2heuc->%&gd#b9lZcvMO^dZEv)^4j|tLc^6 zGMPMQF}hN0bFDIkiz*My5hkwmKo(Z_)OA>~!|iSn|I77`i4`xTXPZaN(=supxZ_R#p%D+v!^kd_@3BO9%cx2iONtX&f8TZWX$>z{@659Tg zefZOq96f?Rlu*%nII3*K?GN{iYsj)S)LI{&(%-97P7+T(lnqm}2M0=6PRw+p!P3J? zVimvWqnf_$tTPR%<#67haM#zCcAV-NR%c2S|Jb(@d2J29d0QOrs;KAN*?a!Sy9`el=#!kdn5~KKpE5DOGeFlza!48j$m> z)3C2-8ESCXf9w(OQXk4%B!1vri6$xB&C;ALzSvh66j6&q&}wGog|4EoMYVf;ExX#c zQqf?FeAgTv*uvI_t=ZI9xm(-fpBen)#O;~m-CviQlV2vtE-#j#h$a-yfxN^pf zMYSb!PaW*4D-03a9u}#@?}%eZ-H6Cq1zEHrUI>jBEQ)wxw^FQrxOSyUQ+9U9wQtI9 zb7g0_^31;SHT1iufNUQ*VGMl3E3Ba(Ly4r%SFQfRfWLp&C+;O{A;Z6dArDq|Hz>@J zi+q-d{j{p{BTH5_XRYFkdmWDU9ob}`1*$QV`e>Og) zEy5~M_DDyi*4V1fL34JC=+TpYJ^CxZ9z9YwH?memp!1>?a=qgG2WwY~96?WZr9Y6Z z+27Q7K@~6Lz#z+%i&i+o11+?uS6I*|6g!0yx2S;-wC~zqea(Nd7rNVp^QW{p{0zRb zYjDpM%(GVr&bbz1K{;WDUElF$PdEOzHYQm6QcSG1QN2*NZ>Z27e9`h%+<62OtTnp7 z%E7WZ&aB3Dfuk?h9Vu43w&=O;raPA8B?wXY@|9jGR{bX3 z&LcRP(V*k2`FlrJV%q>)$?HliHsuY2yhE_i9fJ6S8++Lx;e6Zzod4)M=u*2pl&+ua z@RJO6?S_oF^B21G_0D@o{g2EUeBY=f8WK);GM!i@4+*?@Jb};u;3<4M{y8KZcOf__ K2#ym2{{AoKVbx~< literal 0 HcmV?d00001 diff --git a/release/LD-TRDOS.EXE b/release/LD-TRDOS.EXE new file mode 100644 index 0000000000000000000000000000000000000000..af817c0dc77b59b1db6f38d56eb802a6e754aa55 GIT binary patch literal 19920 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 lN1_Q&rV+dBA)yzaFZB5zJVj3<