home *** CD-ROM | disk | FTP | other *** search
/ Go64! / Go64_1999-06_1999_CSW_Side_A.d64 / 1581cp50.zip / SRC / FDCLOWLV.C < prev    next >
C/C++ Source or Header  |  1999-05-13  |  34KB  |  1,074 lines

  1. /*
  2.  
  3.  * cOPYRIGHT (c) 1998, 1999 wOLFGANG mOSER
  4.  
  5.  *
  6.  
  7.  * tHIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
  8.  
  9.  * IT UNDER THE TERMS OF THE gnu gENERAL pUBLIC lICENSE AS PUBLISHED BY
  10.  
  11.  * THE fREE sOFTWARE fOUNDATION; EITHER VERSION 2, OR (AT YOUR OPTION)
  12.  
  13.  * ANY LATER VERSION.
  14.  
  15.  *
  16.  
  17.  * tHIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
  18.  
  19.  * BUT without any warranty; WITHOUT EVEN THE IMPLIED WARRANTY OF
  20.  
  21.  * merchantability OR fitness for a particular purpose.  sEE THE
  22.  
  23.  * gnu gENERAL pUBLIC lICENSE FOR MORE DETAILS.
  24.  
  25.  *
  26.  
  27.  * yOU SHOULD HAVE RECEIVED A COPY OF THE gnu gENERAL pUBLIC lICENSE
  28.  
  29.  * ALONG WITH THIS PROGRAM (SEE THE FILE copying); IF NOT, WRITE TO THE
  30.  
  31.  * fREE sOFTWARE fOUNDATION, iNC., 675 mASS aVE, cAMBRIDGE, ma 02139, usa.
  32.  
  33.  */
  34.  
  35.  
  36.  
  37. /*
  38.  
  39.  * cOMMODORE cbm 1581 FLOPPY DISK COPY UTIL FOR pc'S, fdclowlv.c
  40.  
  41.  *
  42.  
  43.  * wOLFGANG mOSER <WOMO@MINDLESS.COM>
  44.  
  45.  *   HTTP://WWW.GM.FH-KOELN.DE/{$7e}WOMO (UP TO dEZEMBER 1999)
  46.  
  47.  *
  48.  
  49.  *
  50.  
  51.  * bASIC INFORMATIONS FROM dAN fANDRICH <DAN@FCH.WIMSEY.BC.CA>.
  52.  
  53.  *   hIS README OF THE CBMFS-0.3 DRIVER FOR lINUX EXPLAINED ME, WHAT THE
  54.  
  55.  *   DIFFERENCE BETWEEN A dos FORMATTED 800 KB DISK AND A cbm 1581 DISK IS.
  56.  
  57.  *   (CHECK: HTTP://VANBC.WIMSEY.COM/{$7e}DANF/SOFTWARE/)
  58.  
  59.  *
  60.  
  61.  *
  62.  
  63.  * bASIC IMPLEMENTATIONS BY cIRIACO gARC{CBM-K}A DE cELIS <CIRI@GUI.UVA.ES>
  64.  
  65.  *   hIS UTIL 765dEBUG, vERSION 5.0 IS GREAT FOR LEARNING DMA BASED
  66.  
  67.  *   DIRECT FLOPPY DISK CONTROLLER PROGRAMMING.
  68.  
  69.  *   (CHECK: FTP://FTP.GUI.UVA.ES/PUB/PC/2M/765D50SR.ZIP)
  70.  
  71.  *
  72.  
  73.  * cHECK OUT FOR HIS FLOPPY DISK UTILS 2m AND 2mgui, THE LAST WORDS
  74.  
  75.  * IN IMPROVING FLOPPY DISK STORAGE CAPACITY.
  76.  
  77.  *   HTTP://WWW.GUI.UVA.ES/2M, FTP://FTP.GUI.UVA.ES/PUB/PC/2M
  78.  
  79.  *
  80.  
  81.  *
  82.  
  83.  * fOR ADDITIONAL INFORMATIONS TO fdc PROGRAMMING CHECK:
  84.  
  85.  *     HTTP://DEVELOPER.INTEL.COM/DESIGN/PERIPHRL/DATASHTS/290468.HTM
  86.  
  87.  *   AND GET THE INTEL 82078 chmos sINGLE-cHIP fLOPPY dISK cONTROLLER
  88.  
  89.  *   pdf DOCUMENT:
  90.  
  91.  *     HTTP://WWW.INTEL.NL/DESIGN/PERIPHRL/DATASHTS/29047403.PDF
  92.  
  93.  *   nATIONAL sEMICONDUCTOR HAS ALSO SOME PAGES ABOUT THEIR pc
  94.  
  95.  *   COMPATIBLE CONTROLLERS:
  96.  
  97.  *     HTTP://WWW.NATIONAL.COM/PF/dp/dp8473.HTML
  98.  
  99.  *     HTTP://WWW.NATIONAL.COM/PF/dp/dp8477b.HTML
  100.  
  101.  *
  102.  
  103.  * aNOTHER GOOD SOURCE FOR FLOPPY DISK CONTROLLER PROGRAMMING INFORMATION
  104.  
  105.  * ARE THE LINUX KERNAL SOURCES, YOU COULD HAVE A LOOK INTO:
  106.  
  107.  *     HTTP://WWW.CS.UTEXAS.EDU/USERS/PETERSON/LINUX/INCLUDE/LINUX/FDREG.H
  108.  
  109.  *     HTTP://WWW.CS.UTEXAS.EDU/USERS/PETERSON/LINUX/DRIVERS/BLOCK/FLOPPY.C
  110.  
  111.  */
  112.  
  113.  
  114.  
  115.  
  116.  
  117. #INCLUDE "FDCLOWLV.H"
  118.  
  119.  
  120.  
  121. #IFDEF use_tsc
  122.  
  123. #IFDEF use_p_rdtsc
  124.  
  125. // SPECIAL: pENTIUM tIME sTAMP cOUNTER READ ROUTINE
  126.  
  127. // !!! DOESN'T WORK UNDER ms emm !!! (BUT WITH qemm 7.04)
  128.  
  129. // READS ONLY THE LOWER DWORD
  130.  
  131.  
  132.  
  133. UNSIGNED LONG INT READ_TSC(VOID){$7b}
  134.  
  135. UNSIGNED LONG INT L,H;
  136.  
  137.  
  138.  
  139. ASM{$7b}
  140.  
  141. DB 0X0F, 0X31// OPCODE:   RDTSC
  142.  
  143. DB 0X66; MOV WORD PTR L, AX// OPCODE:   MOV L, EAX
  144.  
  145. DB 0X66; MOV WORD PTR H, DX   // OPCODE: MOV H, EAX
  146.  
  147. {$7d}
  148.  
  149. RETURN L;
  150.  
  151. {$7d}
  152.  
  153.  
  154.  
  155. UNSIGNED LONG INT DIFF_tsc(UNSIGNED LONG INT LASTtsc, UNSIGNED LONG INT NEWtsc){$7b}
  156.  
  157. UNSIGNED LONG INT DIFF;
  158.  
  159.  
  160.  
  161. DIFF=NEWtsc-LASTtsc;
  162.  
  163.    RETURN DIFF;
  164.  
  165. {$7d}
  166.  
  167. // SPECIAL
  168.  
  169.  
  170.  
  171. #ELSE
  172.  
  173. UNSIGNED LONG INT READ_TSC(VOID){$7b}
  174.  
  175. UNION{$7b}
  176.  
  177. UNSIGNED LONG INT TSC;
  178.  
  179. STRUCT{$7b}
  180.  
  181. SIGNED SHORT INT L;
  182.  
  183. SIGNED SHORT INT H;
  184.  
  185. {$7d} LH;
  186.  
  187. {$7d}lLH;
  188.  
  189.  
  190.  
  191. ASMPUSHF// sAVE CURRENT INTERRUPT FLAG
  192.  
  193. ASMCLI// dISABLE INTERRUPTS
  194.  
  195.  
  196.  
  197. // USING SYSTEM TIMER AND TICKS COUNTER INSTEAD OF RDTSC
  198.  
  199. ASMMOVAX,0X40
  200.  
  201. ASMMOVES,AX
  202.  
  203. ASMMOVDX,ES:[0X6c]
  204.  
  205. //lLH.LH.H=PEEK(0X40, 0X6c);
  206.  
  207.  
  208.  
  209. ASMMOVAL,0X00
  210.  
  211. ASMOUT0X43,AL// lATCH TIMER 0
  212.  
  213.  
  214.  
  215. ASMINAL,0X61// wASTE SOME TIME (WAITSTATED)
  216.  
  217.  
  218.  
  219. ASMINAL,0X40// cOUNTER --> BX
  220.  
  221. ASMMOVBL,AL// lsb IN bl
  222.  
  223.  
  224.  
  225. ASMINAL,0X61// wASTE SOME TIME (WAITSTATED)
  226.  
  227.  
  228.  
  229. ASMINAL,0X40
  230.  
  231. ASMMOVBH,AL// msb IN bh
  232.  
  233. ASMNOTBX// nEED ASCENDING COUNTER
  234.  
  235.  
  236.  
  237. ASMPOPF// rESTORE INTERRUPT FLAG
  238.  
  239.  
  240.  
  241.  
  242.  
  243. ASM   MOVCL,15
  244.  
  245. ASMMOVDI,BX    // iF THE msb OF THE SYSTEM TIMER
  246.  
  247. ASMSARDI,CL// IS SET, THEN THE SECOND
  248.  
  249.  
  250.  
  251. ASMANDDX,DI// MEASURED TICKS COUNTER VALUE
  252.  
  253. ASMNOTDI// IS SELECTED, OTHERWISE THE
  254.  
  255.  
  256.  
  257. ASMMOVAX,0X40
  258.  
  259. ASMMOVES,AX
  260.  
  261. ASMMOVCX,ES:[0X6c]
  262.  
  263.    //H=PEEK(0X40, 0X6c);
  264.  
  265. ASMANDCX,DI// FIRST MEASURED TICKS COUNTER
  266.  
  267. ASMORDX,CX// VALUE IS SELECT AS HIGH WORD
  268.  
  269.  
  270.  
  271. ASM   MOVAX,BX// SYSTEM TIMER VALUE IS LOW WORD
  272.  
  273.  
  274.  
  275. lLH.LH.L=_bx;
  276.  
  277. lLH.LH.H=_dx;
  278.  
  279.  
  280.  
  281. RETURN lLH.TSC;
  282.  
  283. {$7d}
  284.  
  285.  
  286.  
  287. UNSIGNED LONG INT DIFF_tsc(UNSIGNED LONG INT LASTtsc, UNSIGNED LONG INT NEWtsc){$7b}
  288.  
  289. UNSIGNED LONG INT DIFF;
  290.  
  291.  
  292.  
  293. DIFF=NEWtsc-LASTtsc;
  294.  
  295.  DIFF+=(DIFF&0X80000000l)>>15;// UNDETECTED OVERFLOW FIX
  296.  
  297.    RETURN DIFF;
  298.  
  299. {$7d}
  300.  
  301. #ENDIF
  302.  
  303. STATIC VOID PRINT_tZ_SINCE(VOID){$7b}
  304.  
  305. STATIC UNSIGNED LONG INT LASTtSC;
  306.  
  307. UNSIGNED LONG INT NEWtSC;
  308.  
  309.  
  310.  
  311. NEWtSC=READ_TSC();
  312.  
  313. PRINTF(" SYSTEM CLOCK CYCLES SINCE LAST: %10LD\N", DIFF_tsc(LASTtSC,NEWtSC));
  314.  
  315. LASTtSC=NEWtSC;
  316.  
  317. {$7d}
  318.  
  319. // SPECIAL
  320.  
  321. #ENDIF
  322.  
  323.  
  324.  
  325. // cbm1581 FLOPPY DISK PARAMETER SET
  326.  
  327.  
  328.  
  329. // lINUX: /ETC/FDPRM ENTRY FOR CBM1581 FILESYSTEM DRIVER
  330.  
  331. // #               SIZE SEC/T HDS TRK STRE GAP  RATE SPEC1 FMT_GAP
  332.  
  333. // CBM1581         1600    10   2  80    2 0X2a 0X02 0Xdf     0X2e
  334.  
  335. //                                      ^
  336.  
  337. // bIT 2 OF THE STRETCH PARAMETER CONTROLS ON lINUX SYSTEMS, THAT
  338.  
  339. // THE DISK SIDE NUMBERS IN THE SECTOR HEADER id FIELDS ARE SWAPPED.
  340.  
  341.  
  342.  
  343. // tHE CBMFS-0.3 gap SIZES ARE NOT PERFECT. tHE ORIGINAL cbm 1581
  344.  
  345. // FORMAT gap SIZE IS: 0X23 AND A BETTER WORKING READ/WRITE gap SIZE
  346.  
  347. // IS 0X0c. i TAKE THESE VALUES AS STANDARDS FOR THE FOLLOWING
  348.  
  349. // DEFAULT INITIALISATION OF THE INTERNAL fdc PARAMETER SET TABLE.
  350.  
  351.  
  352.  
  353. fdcPARAMETERsET fdPRM={$7b}
  354.  
  355.   80,// cYLINDERS:   80 CYLINDERS PER DISK
  356.  
  357.    2,// hEADS:        2 SIDES (TRACKS) PER CYLINDER
  358.  
  359.   10,// sECTORS:     10 SECTORS PER TRACK (SIDE)
  360.  
  361.    2,// bPs:        512 BYTES PER SECTOR
  362.  
  363.    2,// rATE:       250 KILOBIT PER SECOND
  364.  
  365.    1,// mODULATION: mfm
  366.  
  367. 0Xdf,// sPECIFYcmd
  368.  
  369. 0X0c,// rwgap3:      12
  370.  
  371. 0X23,// fMTgap:      35
  372.  
  373. 0X00// pATTERN:      0
  374.  
  375. {$7d};
  376.  
  377.  
  378.  
  379. STATIC UINT8 fdcCOMMANDsTRING[9];
  380.  
  381.  
  382.  
  383. // FILLS UP A 9 BYTE COMMAND SEQUENCE WITH THE STANDARD PARAMETERS
  384.  
  385. //
  386.  
  387. // INPUT:  NONE
  388.  
  389. // OUTPUT: NONE
  390.  
  391. //
  392.  
  393. STATIC VOID PREFILL9CMD(VOID){$7b}
  394.  
  395.    fdcCOMMANDsTRING[5]=fdPRM.bPs;
  396.  
  397.    fdcCOMMANDsTRING[6]=fdPRM.sECTORS;
  398.  
  399.    fdcCOMMANDsTRING[7]=fdPRM.rwgap3;
  400.  
  401.    fdcCOMMANDsTRING[8]=128;
  402.  
  403. {$7d}
  404.  
  405.  
  406.  
  407.  
  408.  
  409. // WAITS UNTIL THE fdc IS READY (COMMAND PHASE)
  410.  
  411. //
  412.  
  413. // INPUT:  A POINTER TO A BYTE, WHERE THE LAST STATUS IS STORED TO
  414.  
  415. //         THIS POINTER CAN BE null, TOO
  416.  
  417. // OUTPUT: 1, IF THE fdc IS READY FOR COMMAND TRANSFERS
  418.  
  419. //         0, IF A TIMEOUT OCCURED
  420.  
  421. //
  422.  
  423. INT WAITuNTILrEADY4tRANSFER(UINT8 *stat){$7b}// TIME OUT AFTER 440 MS
  424.  
  425. INT   T,I=fdc_timeout;
  426.  
  427.    UINT8 DUMMY;
  428.  
  429.  
  430.  
  431.    IF(stat==null) stat=&DUMMY;
  432.  
  433. DO{$7b}
  434.  
  435. T=PEEKB(0X40, 0X6c);
  436.  
  437. WHILE(T==PEEKB(0X40, 0X6c)){$7b}
  438.  
  439. IF((*stat=INPORTB(fd_status))&0X80) RETURN 1;
  440.  
  441. {$7d}
  442.  
  443. {$7d}WHILE (I-->0);
  444.  
  445. RETURN 0;
  446.  
  447. {$7d}
  448.  
  449.  
  450.  
  451. // READ A BYTE FROM THE fdc DATA REGISTER
  452.  
  453. //
  454.  
  455. // INPUT:  NONE
  456.  
  457. // OUTPUT: 0...255: THE CORRECT BYTE FROM THE fdc
  458.  
  459. //         -1:      A TIMEOUT OCCURED (READ OPERATION)
  460.  
  461. //
  462.  
  463. INT INfdc(VOID){$7b}
  464.  
  465. UINT8 STATUS;
  466.  
  467. RETURN WAITuNTILrEADY4tRANSFER(&STATUS)?INPORTB (fd_data):-1;
  468.  
  469. {$7d}
  470.  
  471.  
  472.  
  473. // CLEARS THE fdc COMMAND REGISTERS, WHEN A PREVIOUS OPERATION
  474.  
  475. // WAS ABORTED FOR SOME REASON AND THE fdc COULDN'T RETURN TO
  476.  
  477. // THE COMMAND PHASE
  478.  
  479. //
  480.  
  481. // INPUT:  NONE
  482.  
  483. // OUTPUT: NONE
  484.  
  485. //
  486.  
  487. VOID CLEARfdcRESULTS(VOID){$7b}
  488.  
  489. WHILE((INPORTB(fd_status)&0Xc0)==0Xc0){$7b}
  490.  
  491. DELAY(2);
  492.  
  493. INfdc();// CLEAR fdc DATA REGISTER,
  494.  
  495. DELAY(2);// GET ALL RETURN VALUES
  496.  
  497. {$7d}
  498.  
  499.    {$7d}
  500.  
  501.  
  502.  
  503. // WRITE A BYTE TO THE fdc DATA REGISTER
  504.  
  505. //
  506.  
  507. // INPUT:  THE BYTE TO WRITE
  508.  
  509. // OUTPUT:  1: OPERATION WAS PERFORMED CORRECTLY
  510.  
  511. //         -1: A TIMEOUT OCCURED (WRITE OPERATION)
  512.  
  513. //
  514.  
  515. INT OUTfdc(UINT8 DATA){$7b}
  516.  
  517. UINT8 STATUS;
  518.  
  519.  
  520.  
  521.    DO{$7b}
  522.  
  523.    CLEARfdcRESULTS();// GET OLD RESULT BYTES, IF THERE ARE ANY
  524.  
  525. IF(!WAITuNTILrEADY4tRANSFER(&STATUS)) RETURN -2;// fdc NOT RESPONDING (OUTfdc)
  526.  
  527.    {$7d}WHILE(STATUS&0X40);
  528.  
  529. OUTPORTB(fd_data, DATA);
  530.  
  531. RETURN 1;
  532.  
  533. {$7d}
  534.  
  535.  
  536.  
  537. // PREPARE THE dma CONTROLLER FOR THE TRANSFER TO/FROM THE fdc
  538.  
  539. //
  540.  
  541. // INPUT:  MODE: bITFIELDS FOR dma CHANNEL 0-3 MODE REGISTER (PORT 0X0b):
  542.  
  543. //
  544.  
  545. //bIT(S)dESCRIPTION
  546.  
  547. //
  548.  
  549. //7-6  TRANSFER MODE  5  DIRECTION
  550.  
  551. //             ----------------------------------------------------
  552.  
  553. // 00 DEMAND MODE  0 ADDRESS INCREMENT SELECT
  554.  
  555. // 01 SINGLE MODE  1 ADDRESS DECREMENT SELECT
  556.  
  557. // 10 BLOCK MODE
  558.  
  559. // 11 CASCADE MODE
  560.  
  561. //
  562.  
  563. //3-2OPERATION1-0  CHANNEL NUMBER
  564.  
  565. //             ----------------------------------------------------
  566.  
  567. // 00 VERIFY OPERATION     00 CHANNEL 0 SELECT
  568.  
  569. // 01 WRITE TO MEMORY      01 CHANNEL 1 SELECT
  570.  
  571. // 10 READ FROM MEMORY     10 CHANNEL 2 SELECT
  572.  
  573. // 11 RESERVED             11 CHANNEL 3 SELECT
  574.  
  575. //
  576.  
  577. //         BYTES:  THE NUMBER OF BYTES, THAT HAVE TO BE TRANSFERRED
  578.  
  579. //         dmaBUF: THE POINTER TO THE dma TRANSFER BUFFER
  580.  
  581. // OUTPUT: NONE
  582.  
  583. //
  584.  
  585. VOID PREPAREdma(UINT8 MODE, UINT16 BYTES,
  586.  
  587.  UINT8 HUGE *dmaBUF){$7b}
  588.  
  589.  
  590.  
  591. UNSIGNED LONGFLAT;
  592.  
  593. UNSIGNED SHORTPAGE, OFFS;
  594.  
  595.  
  596.  
  597. // NORMALIZE POINTER
  598.  
  599. FLAT= ((UNSIGNED LONG)fp_seg(dmaBUF)<<4)+fp_off(dmaBUF);
  600.  
  601. PAGE= FLAT>>16;
  602.  
  603. OFFS= FLAT&0Xffff;
  604.  
  605. // DECREMENT TO THE HIGHEST ("ARRAY") INDEX NUMBER
  606.  
  607. BYTES--;
  608.  
  609.  
  610.  
  611. #IFDEF disable_ints
  612.  
  613. DISABLE();
  614.  
  615. #ENDIF
  616.  
  617. OUTPORTB (0X81, PAGE);// dma CHANNEL 2 ADDRESS BYTE 2
  618.  
  619. OUTPORTB (0X0b, MODE);// dma CHANNEL 0-3 MODE REGISTER
  620.  
  621. OUTPORTB (0X0c, 0);// dma CLEAR BYTE POINTER FLIP-FLOP
  622.  
  623. OUTPORTB (0X04, OFFS&0Xff);   // dma CHANNEL 2 ADDRESS BYTE 0
  624.  
  625. OUTPORTB (0X04, OFFS>>8);     // dma CHANNEL 2 ADDRESS BYTE 1
  626.  
  627. OUTPORTB (0X05, BYTES&0Xff);// dma CHANNEL 2 WORD COUNT BYTE 0
  628.  
  629. OUTPORTB (0X05, BYTES>>8);// dma CHANNEL 2 WORD COUNT BYTE 1
  630.  
  631. OUTPORTB (0X0a, 2);// CLEAR MASK BIT OF dma CHANNEL 2
  632.  
  633. #IFDEF disable_ints
  634.  
  635. ENABLE();
  636.  
  637. #ENDIF
  638.  
  639. {$7d}
  640.  
  641.  
  642.  
  643. // WAIT UNTIL THE fdc SENDS AN irq
  644.  
  645. //
  646.  
  647. // INPUT:  TIMEOUTTHE NUMBER OF TIMER TICKS AT LEAST TO WAIT FOR AN irq
  648.  
  649. // OUTPUT: NONE
  650.  
  651. //
  652.  
  653. VOID WAITuNTILiNTERRUPT(INT TIMEOUT){$7b}// TIME OUT AFTER 2 SECONDS
  654.  
  655. INT T;// ,I=op_timeout;
  656.  
  657.  
  658.  
  659. T=PEEKB(0X40, 0X6c);
  660.  
  661. DO{$7b}
  662.  
  663. IF(T!=PEEKB(0X40, 0X6c)){$7b}
  664.  
  665. T=PEEKB(0X40,0X6c);
  666.  
  667. IF(TIMEOUT--<0) BREAK;// WAIT _AT LEAST_ THE NUMBER OF TICKS
  668.  
  669.          {$7d}
  670.  
  671. {$7d}WHILE(!(PEEKB(0X40,0X3e)&0X80));
  672.  
  673. POKEB(0X40,0X3e,PEEKB(0X40,0X3e)&0X7f);
  674.  
  675. {$7d}
  676.  
  677.  
  678.  
  679. // SWITCH THE MOTOR FROM THE SELECTED DRIVE TO ON
  680.  
  681. //
  682.  
  683. // INPUT:  THE DRIVE SELECTED
  684.  
  685. // OUTPUT: NONE
  686.  
  687. //
  688.  
  689. VOID SWITCHmOTORoN(UINT8 DRIVE){$7b}
  690.  
  691. INT I;
  692.  
  693. // 0040H:0040H - diskette - motor turn-off timeout count
  694.  
  695. POKEB(0X40,0X40,0Xff);
  696.  
  697. // 0040H:003fH - diskette - motor status
  698.  
  699. IF(((I=PEEKB(0X40,0X3f))&(1<<DRIVE))==0){$7b}
  700.  
  701. OUTPORTB(fd_dor,(1<<(DRIVE+4)){$7c}(4+8){$7c}DRIVE);
  702.  
  703. POKEB(0X40,0X3f,I{$7c}(1<<DRIVE));
  704.  
  705. DELAY(1000);
  706.  
  707. POKEB(0X40,0X40,0Xff);
  708.  
  709. {$7d}
  710.  
  711. {$7d}
  712.  
  713.  
  714.  
  715. // SWITCH THE MOTORS FROM ALL DRIVES TO OFF
  716.  
  717. //
  718.  
  719. // INPUT:  NONE
  720.  
  721. // OUTPUT: NONE
  722.  
  723. //
  724.  
  725. VOID SWITCHmOTORoFF(VOID){$7b}
  726.  
  727. // 0040H:0040H - diskette - motor turn-off timeout count
  728.  
  729. POKEB(0X40,0X40,55);
  730.  
  731. {$7d}
  732.  
  733.  
  734.  
  735. // SEND ALL SPECIFICATIONS FOR THE CURRENT DRIVE TO THE fdc
  736.  
  737. //
  738.  
  739. // INPUT:  NONE
  740.  
  741. // OUTPUT: NONE
  742.  
  743. //
  744.  
  745. VOID SPECIFYdENSITY(VOID){$7b}
  746.  
  747. OUTPORTB(fd_dcr, fdPRM.bITRATE);// SELECT BITRATE (DISK DENSITY)
  748.  
  749. IF(OUTfdc(3)<0 {$7c}{$7c}// SPECIFY COMMAND
  750.  
  751. OUTfdc(fdPRM.sPECIFYcmd)<0 {$7c}{$7c}// HEAD UNLOAD TIME, STEP RATE TIME
  752.  
  753. OUTfdc(0X02)<0// HEAD LOAD TIME, SWITCH TO dma MODE
  754.  
  755. );// THIS IS A TRICK: IF ONE OPERATION FAILS, THE FOLLOWING ARE NOT DONE
  756.  
  757. {$7d}
  758.  
  759.  
  760.  
  761. // SELECTS A DRIVE FOR THE FOLLOWING OPERATIONS
  762.  
  763. //
  764.  
  765. // INPUT:  NONE
  766.  
  767. // OUTPUT: NONE
  768.  
  769. //
  770.  
  771. VOID SELECTdRIVE(UINT8 DRIVE){$7b}
  772.  
  773. // 0040H:0040H - diskette - motor turn-off timeout count
  774.  
  775. POKEB(0X40,0X40,0Xff);
  776.  
  777. // SELECT DRIVE, RESET fdc, MOTOR ON
  778.  
  779. OUTPORTB(fd_dor,(1<<(DRIVE+4)){$7c}(4+8){$7c}DRIVE);
  780.  
  781. POKEB(0X40,0X3f,PEEKB(0X40,0X3f){$7c}(1<<DRIVE));
  782.  
  783.  
  784.  
  785. SPECIFYdENSITY();
  786.  
  787. {$7d}
  788.  
  789.  
  790.  
  791. // ISSUE A fdc COMMAND WITH dma TRANSFER (INTERNAL LIB USE ONLY)
  792.  
  793. //
  794.  
  795. // INPUT:  cmdLEN:       THE LENGTH OF THE COMMAND STRING
  796.  
  797. //         dmaMODE:      THE dma MODE TO SELECT FOR THIS COMMAND
  798.  
  799. //         dmaBYTES:     THE NUMBER OF BYTES TO TRANSFER WITH dma
  800.  
  801. //         dmaBUFFER:    THE dma TRANSFER BUFFER
  802.  
  803. // OUTPUT: 0 - TIMOUT WHILE SENDING A COMMAND TO THE fdc
  804.  
  805. //         1 - OPERATION WAS SUCCESSFUL
  806.  
  807. STATIC INT ISSUEcMD(UINT8 cmdLEN,
  808.  
  809. UINT8 dmaMODE, UINT16 dmaBYTES, UINT8 HUGE *dmaBUF){$7b}
  810.  
  811. INT I;
  812.  
  813.  
  814.  
  815. SELECTdRIVE(fdcCOMMANDsTRING[1]&3);
  816.  
  817. SWITCHmOTORoN(fdcCOMMANDsTRING[1]&3);// SET AGAIN TIMEOUT COUNT
  818.  
  819.  
  820.  
  821.  
  822.  
  823. #IF (messages >= 6)
  824.  
  825. FPRINTF(STDERR,"fdc COMMAND: 0X");
  826.  
  827.    FOR(I=0;I<cmdLEN;I++) FPRINTF(STDERR,"%02x.",fdcCOMMANDsTRING[I]);
  828.  
  829.    FPRINTF(STDERR,"  dma: 0X%02x, 0X%04x, 0X%05Lx\N",dmaMODE,dmaBYTES,
  830.  
  831. ((UNSIGNED LONG)fp_seg(dmaBUF)<<4)+fp_off(dmaBUF));
  832.  
  833. //   PRINTF("\N");
  834.  
  835. #ENDIF
  836.  
  837.  
  838.  
  839.  
  840.  
  841. PREPAREdma(dmaMODE, dmaBYTES, dmaBUF);
  842.  
  843.    FOR(I=0;I<cmdLEN;I++)
  844.  
  845. IF(OUTfdc(fdcCOMMANDsTRING[I])<0) RETURN 0;
  846.  
  847. WAITuNTILiNTERRUPT(op_timeout);
  848.  
  849. RETURN 1;
  850.  
  851. {$7d}
  852.  
  853.  
  854.  
  855. // PERFORMS THE SENSE INTERRUPT STATUS COMMAND
  856.  
  857. //
  858.  
  859. // INPUT:  POINTER TO THE RESULT STRING STRUCTURE
  860.  
  861. // OUTPUT: 1 - OPERATION WAS SUCCESSFUL
  862.  
  863. //         0 - OPERATION WAS UNSUCCESSFUL
  864.  
  865. //    THE RESULT STRING HOLDS st0 AND THE cYLINDER VALUE
  866.  
  867. //
  868.  
  869. INT SENSEiNTERRUPTsTAT(RESULTsTRING *RESsTR){$7b}
  870.  
  871. INT RES;
  872.  
  873.  
  874.  
  875.    IF(RESsTR==null) RETURN 0;
  876.  
  877.  
  878.  
  879. FOR(RES=0;RES<8;RES++) RESsTR->sTATUS[RES]=0;
  880.  
  881. IF(OUTfdc(8)>=0){$7b}// SENSE INTERRUPT STATUS COMMAND
  882.  
  883.    RESsTR->d.st0=INfdc();
  884.  
  885.    IF(RESsTR->d.st0>0){$7b}
  886.  
  887.    RES=INfdc();
  888.  
  889.    IF(RES>0){$7b}
  890.  
  891.    RESsTR->d.cYLINDER=RES;
  892.  
  893.    RETURN 1;
  894.  
  895.    {$7d}
  896.  
  897.    {$7d}
  898.  
  899.       {$7d}
  900.  
  901. RETURN 0;
  902.  
  903. {$7d}
  904.  
  905.  
  906.  
  907. // PERFORMS A DRIVE RESET
  908.  
  909. //
  910.  
  911. // INPUT:  THE DRIVE, THAT SHOULD BE RESETTED
  912.  
  913. // OUTPUT: NONE
  914.  
  915. //
  916.  
  917. VOID RESETdRIVE(UINT8 DRIVE){$7b}
  918.  
  919. RESULTsTRING rs;
  920.  
  921.  
  922.  
  923. POKEB(0X40,0X3e,PEEKB(0X40,0X3e)&0X7f);// CLEAR INTERRUPT BIT
  924.  
  925.  
  926.  
  927. OUTPORTB(fd_dor,(1<<(DRIVE+4)){$7c}DRIVE{$7c}8);// RESET
  928.  
  929. DELAY(2);
  930.  
  931. OUTPORTB(fd_dor,(1<<(DRIVE+4)){$7c}DRIVE{$7c}(8+4));// FINISH RESET
  932.  
  933.  
  934.  
  935. WAITuNTILiNTERRUPT(op_timeout);
  936.  
  937.  
  938.  
  939. SENSEiNTERRUPTsTAT(&rs);
  940.  
  941. {$7d}
  942.  
  943.  
  944.  
  945. // GETS A SEVEN BYTE RESULT STRING FROM THE fdc
  946.  
  947. //
  948.  
  949. // INPUT:  POINTER TO THE RESULT STRING STRUCTURE
  950.  
  951. // OUTPUT: 1 - OPERATION WAS SUCCESSFUL
  952.  
  953. //         0 - OPERATION WAS UNSUCCESSFUL
  954.  
  955. //    THE RESULT STRING FILLED UP WITH ALL THE VALUES
  956.  
  957. //
  958.  
  959. INT VALID7rESULTsTRING(RESULTsTRING *RESsTR){$7b}
  960.  
  961. INT I,RES;
  962.  
  963.  
  964.  
  965.    IF(RESsTR==null) RETURN 0;
  966.  
  967.  
  968.  
  969. RESsTR->d.st0=INfdc();
  970.  
  971. IF(RESsTR->d.st0<0) RETURN 0;
  972.  
  973.  
  974.  
  975. FOR(I=2;I<8;I++){$7b}
  976.  
  977. RES=INfdc();
  978.  
  979. IF(RES<0){$7b}
  980.  
  981. RESsTR->d.st0=-1;
  982.  
  983. RETURN 0;
  984.  
  985. {$7d}
  986.  
  987. ELSE RESsTR->sTATUS[I]=RES;
  988.  
  989. {$7d}
  990.  
  991. // WONT BE NEEDED, BECAUSE st0 SHOULD REFLECT THE SAME
  992.  
  993. //IF(RESsTR->d.st1 {$7c}{$7c} RESsTR->d.st2) RETURN 0;
  994.  
  995. //
  996.  
  997. RES=RESsTR->d.st0&0Xc0;
  998.  
  999. RETURN !RES;
  1000.  
  1001. {$7d}
  1002.  
  1003.  
  1004.  
  1005. // PRINTS ALL VALUES FROM A RESULT STRING TO THE CONSOLE
  1006.  
  1007. //
  1008.  
  1009. // INPUT:  POINTER TO THE RESULT STRING STRUCTURE
  1010.  
  1011. // OUTPUT: NONE
  1012.  
  1013. //
  1014.  
  1015. VOID PRINTrESULTsTRING(RESULTsTRING *RESsTR){$7b}
  1016.  
  1017. INT  STR, T, BIT;
  1018.  
  1019. STATIC CHAR *STERR[2][8]={$7b}{$7b}
  1020.  
  1021. "ma (mISSING ADDRESS MARK)",
  1022.  
  1023. "nw (nON WRITABLE: WRITE PROTECT ERROR)",
  1024.  
  1025. "nd (nO DATA)",
  1026.  
  1027. "",
  1028.  
  1029. "or (oVERRUN)",
  1030.  
  1031. "de (dATA ERROR)",
  1032.  
  1033. "",
  1034.  
  1035. "en (eND OF CYLINDER)",
  1036.  
  1037. {$7d},{$7b}
  1038.  
  1039. "md (mISSING ADDRESS MARK IN DATA FIELD",
  1040.  
  1041. "bc (bAD CYLINDER)",
  1042.  
  1043. "sn (sCAN NOT SATISFIED)",
  1044.  
  1045. "se (sCAN EQUAL HIT)",
  1046.  
  1047. "wc (wRONG cYLINDER)",
  1048.  
  1049. "dd (dATA eRROR IN dATA fIELD)",
  1050.  
  1051. "cm (cONTROL mARK)",
  1052.  
  1053. ""{$7d}{$7d};
  1054.  
  1055.  
  1056.  
  1057.    IF(RESsTR==null) RETURN;
  1058.  
  1059.  
  1060.  
  1061. IF(RESsTR->d.st0<0) PRINTF("[st0 %4D]   fdc DOESN'T ANSWER! error!\N",RESsTR->d.st0);
  1062.  
  1063. ELSE{$7b}
  1064.  
  1065. PRINTF("[st0 0X%02x] [st1 0X%02x] [st2 0X%02x] [cYL %3D] "
  1066.  
  1067.  "[sIDE %1D] [sEC %2D] [bYTE %3D] : ",
  1068.  
  1069.  RESsTR->d.st0, RESsTR->d.st1, RESsTR->d.st2,
  1070.  
  1071.  RESsTR->d.cYLINDER, RESsTR->d.sIDE,
  1072.  
  1073.  RESsTR->d.sECTOR, RESsTR->d.bYTESps);
  1074.  
  1075. RESsTR->d.st1&=0Xb7;
  1076.  
  1077. RESsTR->d.st2&=0X7f;
  1078.  
  1079.  
  1080.  
  1081. IF(RESsTR->d.st0&0Xc0)PRINTF("error!\N");
  1082.  
  1083. ELSEPRINTF("ok\N");
  1084.  
  1085.  
  1086.  
  1087. FOR(STR=2; STR<=3; STR++) FOR(BIT=0, T=1; BIT<8; BIT++, T<<=1){$7b}
  1088.  
  1089. IF(RESsTR->sTATUS[STR]&T)
  1090.  
  1091. PRINTF("st%C(%C): %S\N",STR+'0'-1,BIT+'0',STERR[STR-2][BIT]);
  1092.  
  1093. {$7d}
  1094.  
  1095. {$7d}
  1096.  
  1097. {$7d}
  1098.  
  1099.  
  1100.  
  1101. // PERFORMS A RECALIBRATION FOR THE SPECIFIED DRIVE (SEEK TO TRACK 0)
  1102.  
  1103. //
  1104.  
  1105. // INPUT:  DRIVE:        THE DRIVE, THAT SHOULD BE RECALIBRATED
  1106.  
  1107. //         SIDE:         THE DISK SIDE (HEAD), THAT SHOULD BE SELECTED
  1108.  
  1109. // OUTPUT: RESULTsTRING: null  - OPERATION WAS SUCESSFUL
  1110.  
  1111. //                       OTHER - THE FILLED UP RESULT STRUCTURE
  1112.  
  1113. //
  1114.  
  1115. RESULTsTRING *RECALIBRATEdRIVE(UINT8 DRIVE, UINT8 SIDE){$7b}
  1116.  
  1117. STATIC RESULTsTRING rs;
  1118.  
  1119. INT TRIES;
  1120.  
  1121.  
  1122.  
  1123. #IFDEF use_tsc
  1124.  
  1125. FPRINTF(STDERR,"%20S","REACLIBRATEdRIVE");
  1126.  
  1127. PRINT_tZ_SINCE();
  1128.  
  1129. #ENDIF
  1130.  
  1131.  
  1132.  
  1133. SELECTdRIVE(DRIVE);
  1134.  
  1135. SWITCHmOTORoN(DRIVE);// SET AGAIN TIMEOUT COUNT
  1136.  
  1137.  
  1138.  
  1139. RESETdRIVE(DRIVE);
  1140.  
  1141. //RESETdRIVE(DRIVE);
  1142.  
  1143. SPECIFYdENSITY();
  1144.  
  1145.  
  1146.  
  1147. FOR(TRIES=2;TRIES>0;TRIES--){$7b}
  1148.  
  1149.    rs.d.st0=-2;// DEFAULT: fdc NOT RESPONDING
  1150.  
  1151. IF(OUTfdc(0X07)<0 {$7c}{$7c}// RECALIBRATE COMMAND
  1152.  
  1153. OUTfdc(((({$7e}SIDE)&1)<<2){$7c}DRIVE)<0
  1154.  
  1155. )RETURN &rs;
  1156.  
  1157.  
  1158.  
  1159. WAITuNTILiNTERRUPT(op_timeout);
  1160.  
  1161.  
  1162.  
  1163. SENSEiNTERRUPTsTAT(&rs);
  1164.  
  1165.  
  1166.  
  1167. IF((rs.d.st0&0Xf0)==0X20 && rs.d.cYLINDER==0U){$7b}
  1168.  
  1169.    rs.d.st0=-2;// DEFAULT: fdc NOT RESPONDING
  1170.  
  1171. IF(OUTfdc(0X04)<0 {$7c}{$7c}// DRIVE STATUS COMMAND (READ st3)
  1172.  
  1173. OUTfdc(((({$7e}SIDE)&1)<<2){$7c}DRIVE)<0
  1174.  
  1175. )RETURN &rs;
  1176.  
  1177. IF(INfdc()&0X10) BREAK;// track0 BIT IS SET, THAT'S OK
  1178.  
  1179.          {$7d}
  1180.  
  1181. {$7d}
  1182.  
  1183. RETURN (TRIES>0)?null:&rs;
  1184.  
  1185. {$7d}
  1186.  
  1187.  
  1188.  
  1189. // PERFORMS A SEEK FOR THE SPECIFIED DRIVE
  1190.  
  1191. //
  1192.  
  1193. // INPUT:  DRIVE:        THE DRIVE, THAT SHOULD DO THE SEEK
  1194.  
  1195. //         CYL:          THE CYLINDER TO SEEK TO
  1196.  
  1197. //         SIDE:         THE DISK SIDE (HEAD), THAT SHOULD BE SELECTED
  1198.  
  1199. // OUTPUT: RESULTsTRING: null  - OPERATION WAS SUCESSFUL
  1200.  
  1201. //                       OTHER - THE FILLED UP RESULT STRUCTURE
  1202.  
  1203. //
  1204.  
  1205. RESULTsTRING *SEEKtOcYL(UINT8 DRIVE, UINT8 CYL, UINT8 SIDE){$7b}
  1206.  
  1207. STATIC RESULTsTRING rs;
  1208.  
  1209.  
  1210.  
  1211. #IFDEF use_tsc
  1212.  
  1213. FPRINTF(STDERR,"%20S","SEEKtOtRACK");
  1214.  
  1215. PRINT_tZ_SINCE();
  1216.  
  1217. #ENDIF
  1218.  
  1219.  
  1220.  
  1221. SELECTdRIVE(DRIVE);
  1222.  
  1223. SWITCHmOTORoN(DRIVE);// SET AGAIN TIMEOUT COUNT
  1224.  
  1225.  
  1226.  
  1227.    rs.d.st0=-2;// DEFAULT: fdc NOT RESPONDING
  1228.  
  1229.    IF(OUTfdc(0X0f)<0 {$7c}{$7c}// SEEK COMMAND
  1230.  
  1231.    OUTfdc(((({$7e}SIDE)&1)<<2){$7c}DRIVE)<0 {$7c}{$7c}
  1232.  
  1233. OUTfdc(CYL)<0
  1234.  
  1235. )RETURN &rs;
  1236.  
  1237.  
  1238.  
  1239. WAITuNTILiNTERRUPT(op_timeout);
  1240.  
  1241.  
  1242.  
  1243. SENSEiNTERRUPTsTAT(&rs);
  1244.  
  1245. IF(rs.d.st0&0Xc0){$7b}
  1246.  
  1247. DELAY(750);
  1248.  
  1249. SENSEiNTERRUPTsTAT(&rs);
  1250.  
  1251. {$7d}
  1252.  
  1253. RETURN((rs.d.st0&0Xf0)==0X20 && rs.d.cYLINDER==CYL)?null:&rs;
  1254.  
  1255. {$7d}
  1256.  
  1257.  
  1258.  
  1259. // GET THE DISK STATUS OF THE SPECIFIED DRIVE
  1260.  
  1261. //
  1262.  
  1263. // INPUT:  DRIVE:        THE DRIVE, THAT SHOULD DO THE SEEK
  1264.  
  1265. // OUTPUT: 0 - THERE'S NO DISK IN THE DRIVE
  1266.  
  1267. //         1 - THE OLD DISK IS IN (SOME OPERATIONS HAVE BEEN DONE BEFORE)
  1268.  
  1269. //         2 - A NEW DISK WAS INSERTED INTO THE DRIVE
  1270.  
  1271. //
  1272.  
  1273. INT SENSEdISKsTATUS(UINT8 DRIVE){$7b}
  1274.  
  1275. //SELECTdRIVE(DRIVE);// THIS MUST NOT BE DONE!!!
  1276.  
  1277. // PERHAPS WE SHOULD DO THIS IN THE OUTER LOOP, BUT i
  1278.  
  1279. // DON'T KNOW, IF THIS WOULD WORK WITH TWO DRIVES THEN
  1280.  
  1281.    //
  1282.  
  1283.    // tHE PROBLEM IS, THAT THE CONTENTS OF fd_status ARE
  1284.  
  1285.    // ALWAYS 0X8x, WHEN i DO THE SELECTdRIVE(...)
  1286.  
  1287.  
  1288.  
  1289. SWITCHmOTORoN(DRIVE);// SET AGAIN TIMEOUT COUNT
  1290.  
  1291.    IF(INPORTB(fd_dcr)&0X80){$7b}// READ "DISK CHANGE" BIT
  1292.  
  1293.  
  1294.  
  1295. DELAY(2);
  1296.  
  1297.       SWITCH(INPORTB(fd_status)&0Xc0){$7b}
  1298.  
  1299.       CASE 0Xc0:// THERE ARE fdc RESULTS TO READ
  1300.  
  1301. POKEB(0X40,0X3e,PEEKB(0X40,0X3e)&0X7f);// CLEAR INTERRUPT (TO BE SURE)
  1302.  
  1303. SEEKtOcYL(DRIVE,1,0);// CLEAR "DISK CHANGE" BIT, THIS
  1304.  
  1305. RECALIBRATEdRIVE(DRIVE,0);// CAN ONLY BE DONE BY DOING A SEEK
  1306.  
  1307. // IF DISK CHANGE BIT IS CLEARED ==> THERE'S A NEW DISK IS IN
  1308.  
  1309.          IF(!(INPORTB(fd_dcr)&0X80)) RETURN 2;
  1310.  
  1311. // ISSUE READsECTORid
  1312.  
  1313.          CASE 0X80:// fdc READY, BUT NO RESULTS
  1314.  
  1315. RECALIBRATEdRIVE(DRIVE,0);// GO TO A MOSTLY FORMATTED TRACK
  1316.  
  1317.    // ISSUE A NEW READsECTORid COMMAND
  1318.  
  1319.                // AND DON'T WAIT FOR ANY RESULTS
  1320.  
  1321. READsECTORid(DRIVE,0,null,-1);
  1322.  
  1323.  
  1324.  
  1325. //OUTfdc(0X0a {$7c} (fdPRM.mODULATION<<6));// ISSUE A NEW
  1326.  
  1327. //OUTfdc(((({$7e}0)&1)<<2) {$7c} DRIVE);// READsECTORid COMMAND
  1328.  
  1329.       {$7d}
  1330.  
  1331.         // AFTER EXECUTING READsECTORid, OR WHEN THE fdc
  1332.  
  1333. // IS BUSY (0B0XXXXXXX), THE DISK IS ASSUMED AS "OUT"
  1334.  
  1335.      RETURN 0;
  1336.  
  1337.    {$7d}
  1338.  
  1339.    RETURN 1;// DISK CHANGE BIT CLEARED ==> OLD DISK IS IN
  1340.  
  1341. {$7d}
  1342.  
  1343.  
  1344.  
  1345. // READ THE NEXT POSSIBLE SECTOR HEADER id FROM THE CURRENT CYLINDER
  1346.  
  1347. //
  1348.  
  1349. // INPUT:  DRIVE:        THE DRIVE TO READ FROM
  1350.  
  1351. //         SIDE:         THE DISK SIDE (HEAD), THAT SHOULD BE SELECTED
  1352.  
  1353. //         HEADER:       A POINTER TO A RESULT STRUCTURE
  1354.  
  1355. //         TIMEOUT:      THE NUMBER OF TIMER TICKS TO WAIT AT LEAST FOR A
  1356.  
  1357. //                       SECTOR HEADER (TIMEOUT<0 MEANS TO _NEVER_ WAIT)
  1358.  
  1359. // OUTPUT: HEADER:       THE RESULT STRING POINTED TO FILLED UP WITH THE RESULT
  1360.  
  1361. //         RETURN:  0 - OPERATION FAILED
  1362.  
  1363. //                  1 - OPERATION WAS SUCCESSFUL
  1364.  
  1365. //
  1366.  
  1367. INT READsECTORid(UINT8 DRIVE, UINT8 SIDE, RESULTsTRING *HEADER, INT TIMEOUT){$7b}
  1368.  
  1369. #IFDEF use_tsc
  1370.  
  1371. FPRINTF(STDERR,"%20S","READsECTORid");
  1372.  
  1373. PRINT_tZ_SINCE();
  1374.  
  1375. #ENDIF
  1376.  
  1377. IF(HEADER==null && TIMEOUT>=0) RETURN 0;
  1378.  
  1379. SELECTdRIVE(DRIVE);
  1380.  
  1381. SWITCHmOTORoN(DRIVE);// SET AGAIN TIMEOUT COUNT
  1382.  
  1383.  
  1384.  
  1385.    HEADER->d.st0=-2;// DEFAULT: fdc NOT RESPONDING
  1386.  
  1387.    IF(OUTfdc(0X0a {$7c} (fdPRM.mODULATION<<6))<0 {$7c}{$7c}
  1388.  
  1389. OUTfdc(((({$7e}SIDE)&1)<<2){$7c}DRIVE)<0
  1390.  
  1391. )RETURN 0;
  1392.  
  1393.  
  1394.  
  1395. IF(TIMEOUT<0) RETURN 0;// NO VALID RESULT, ONLY COMMAND ISSUEING
  1396.  
  1397.  
  1398.  
  1399. WAITuNTILiNTERRUPT(TIMEOUT);
  1400.  
  1401. RETURN VALID7rESULTsTRING(HEADER);
  1402.  
  1403. {$7d}
  1404.  
  1405.  
  1406.  
  1407. // FORMAT A TRACK (ONE SIDE OF A CYLINDER)
  1408.  
  1409. //
  1410.  
  1411. // INPUT:  DRIVE:        THE DRIVE TO FORMAT A TRACK AT
  1412.  
  1413. //         CYL:          THE CYLINDER NUMBER TO BE WRITTEN INTO THE HEADERS
  1414.  
  1415. //         SIDE:         THE DISK SIDE NUMBER TO BE WRITTEN INTO THE HEADERS
  1416.  
  1417. // OUTPUT: RESULTsTRING: null  - OPERATION WAS SUCESSFUL
  1418.  
  1419. //                       OTHER - THE FILLED UP RESULT STRUCTURE
  1420.  
  1421. //
  1422.  
  1423. RESULTsTRING *FORMATcbmTRACK(UINT8 DRIVE, UINT8 CYL, UINT8 SIDE){$7b}
  1424.  
  1425. STATIC RESULTsTRING rs;
  1426.  
  1427. // 4 id BYTES PER SECTOR
  1428.  
  1429. UINT8 fMTbUFFER[mAXsECTORS * 4];// mAXsECTORS IS DEFINED IN central.h
  1430.  
  1431. INTI,J;
  1432.  
  1433.  
  1434.  
  1435.  
  1436.  
  1437. #IFDEF use_tsc
  1438.  
  1439. FPRINTF(STDERR,"%20S","FORMATc1581TRACK");
  1440.  
  1441. PRINT_tZ_SINCE();
  1442.  
  1443. #ENDIF
  1444.  
  1445.  
  1446.  
  1447. FOR(I=J=0;I<fdPRM.sECTORS;){$7b}// FILL UP THE id BYTES
  1448.  
  1449.    I++;// START WITH SECTOR 1
  1450.  
  1451. fMTbUFFER[J++]=CYL;// CYLINDER DESCRIPTOR
  1452.  
  1453. fMTbUFFER[J++]=SIDE;// HEAD DESCRIPTOR
  1454.  
  1455. fMTbUFFER[J++]=I;// SECTOR nO.
  1456.  
  1457. fMTbUFFER[J++]=fdPRM.bPs;
  1458.  
  1459. {$7d}
  1460.  
  1461.  
  1462.  
  1463.    fdcCOMMANDsTRING[0]=(fdPRM.mODULATION<<6) {$7c} 0X0d;
  1464.  
  1465.    fdcCOMMANDsTRING[1]=((({$7e}SIDE)&1)<<2) {$7c} DRIVE;
  1466.  
  1467.    fdcCOMMANDsTRING[2]=fdPRM.bPs;
  1468.  
  1469.    fdcCOMMANDsTRING[3]=fdPRM.sECTORS;
  1470.  
  1471.    fdcCOMMANDsTRING[4]=fdPRM.fMTgap;
  1472.  
  1473.    fdcCOMMANDsTRING[5]=fdPRM.pATTERN;
  1474.  
  1475.  
  1476.  
  1477. IF(!ISSUEcMD(6,0X4a,fdPRM.sECTORS<<2,fMTbUFFER)){$7b}
  1478.  
  1479.    rs.d.st0=-2;// fdc NOT RESPONDING
  1480.  
  1481.       RETURN &rs;
  1482.  
  1483.    {$7d}
  1484.  
  1485.    ELSE{$7b}
  1486.  
  1487. RETURN VALID7rESULTsTRING(&rs)?null:&rs;
  1488.  
  1489.    {$7d}
  1490.  
  1491. {$7d}
  1492.  
  1493.  
  1494.  
  1495. // READ A SECTOR
  1496.  
  1497. //
  1498.  
  1499. // INPUT:  DRIVE:        THE DRIVE TO READ FROM
  1500.  
  1501. //         CYL:          THE CYLINDER NUMBER TO READ FROM
  1502.  
  1503. //         SIDE:         THE DISK SIDE NUMBER TO READ FROM
  1504.  
  1505. //         SECTOR:       THE SECTOR NUMBER TO READ
  1506.  
  1507. //         BUFFER:       A POINTER TO A BUFFER TO READ THE DATA IN
  1508.  
  1509. // OUTPUT: RESULTsTRING: null  - OPERATION WAS SUCESSFUL
  1510.  
  1511. //                       OTHER - THE FILLED UP RESULT STRUCTURE
  1512.  
  1513. //
  1514.  
  1515. RESULTsTRING *READcbmSECTOR(UINT8 DRIVE, UINT8 CYL, UINT8 SIDE,
  1516.  
  1517.  UINT8 SECTOR, UINT8 HUGE *BUFFER){$7b}
  1518.  
  1519. STATIC RESULTsTRING rs;
  1520.  
  1521.  
  1522.  
  1523. #IFDEF use_tsc
  1524.  
  1525. FPRINTF(STDERR,"%20S","READcbmSECTOR");
  1526.  
  1527. PRINT_tZ_SINCE();
  1528.  
  1529. #ENDIF
  1530.  
  1531.  
  1532.  
  1533. PREFILL9CMD();// FILL UP BYTES 5 TO 8
  1534.  
  1535.    fdcCOMMANDsTRING[0]=(fdPRM.mODULATION<<6) {$7c} 0X06;
  1536.  
  1537.    fdcCOMMANDsTRING[1]=((({$7e}SIDE)&1)<<2) {$7c} DRIVE;
  1538.  
  1539.    fdcCOMMANDsTRING[2]=CYL;
  1540.  
  1541.    fdcCOMMANDsTRING[3]=SIDE;
  1542.  
  1543.    fdcCOMMANDsTRING[4]=SECTOR;
  1544.  
  1545.  
  1546.  
  1547.    rs.d.st0=-2;// DEFAULT: fdc NOT RESPONDING
  1548.  
  1549. IF(ISSUEcMD(9,0X46,128U<<fdPRM.bPs,BUFFER) &&
  1550.  
  1551. VALID7rESULTsTRING(&rs)
  1552.  
  1553. )RETURN null;
  1554.  
  1555.    ELSE RETURN &rs;
  1556.  
  1557. {$7d}
  1558.  
  1559.  
  1560.  
  1561. // WRITE A SECTOR
  1562.  
  1563. //
  1564.  
  1565. // INPUT:  DRIVE:        THE DRIVE TO WRITE TO
  1566.  
  1567. //         CYL:          THE CYLINDER NUMBER TO WRITE TO
  1568.  
  1569. //         SIDE:         THE DISK SIDE NUMBER TO WRITE TO
  1570.  
  1571. //         SECTOR:       THE SECTOR NUMBER TO WRITE
  1572.  
  1573. //         BUFFER:       A POINTER TO A BUFFER TO WRITE THE DATA FROM
  1574.  
  1575. // OUTPUT: RESULTsTRING: null  - OPERATION WAS SUCESSFUL
  1576.  
  1577. //                       OTHER - THE FILLED UP RESULT STRUCTURE
  1578.  
  1579. //
  1580.  
  1581. RESULTsTRING *WRITEcbmSECTOR(UINT8 DRIVE, UINT8 CYL, UINT8 SIDE,
  1582.  
  1583.   UINT8 SECTOR, UINT8 HUGE *BUFFER){$7b}
  1584.  
  1585. STATIC RESULTsTRING rs;
  1586.  
  1587.  
  1588.  
  1589. #IFDEF use_tsc
  1590.  
  1591. FPRINTF(STDERR,"%20S","WRITEcbmSECTOR");
  1592.  
  1593. PRINT_tZ_SINCE();
  1594.  
  1595. #ENDIF
  1596.  
  1597.  
  1598.  
  1599. PREFILL9CMD();// FILL UP BYTES 5 TO 8
  1600.  
  1601.    fdcCOMMANDsTRING[0]=(fdPRM.mODULATION<<6) {$7c} 0X05;
  1602.  
  1603.    fdcCOMMANDsTRING[1]=((({$7e}SIDE)&1)<<2) {$7c} DRIVE;
  1604.  
  1605.    fdcCOMMANDsTRING[2]=CYL;
  1606.  
  1607.    fdcCOMMANDsTRING[3]=SIDE;
  1608.  
  1609.    fdcCOMMANDsTRING[4]=SECTOR;
  1610.  
  1611.  
  1612.  
  1613.    rs.d.st0=-2;// DEFAULT: fdc NOT RESPONDING
  1614.  
  1615. IF(ISSUEcMD(9,0X4a,128U<<fdPRM.bPs,BUFFER) &&
  1616.  
  1617. VALID7rESULTsTRING(&rs)
  1618.  
  1619. )RETURN null;
  1620.  
  1621.    ELSE RETURN &rs;
  1622.  
  1623. {$7d}
  1624.  
  1625.  
  1626.  
  1627. // VERIFY A SECTOR
  1628.  
  1629. //
  1630.  
  1631. // INPUT:  DRIVE:        THE DRIVE TO VERIFY AT
  1632.  
  1633. //         CYL:          THE CYLINDER NUMBER TO VERIFY AT
  1634.  
  1635. //         SIDE:         THE DISK SIDE NUMBER TO VERIFY AT
  1636.  
  1637. //         SECTOR:       THE SECTOR NUMBER TO VERIFY
  1638.  
  1639. //         BUFFER:       A POINTER TO A BUFFER TO VERIFY THE DATA WITH
  1640.  
  1641. // OUTPUT: RESULTsTRING: null  - OPERATION WAS SUCESSFUL
  1642.  
  1643. //                       OTHER - THE FILLED UP RESULT STRUCTURE
  1644.  
  1645. RESULTsTRING *VERIFYcbmSECTOR(UINT8 DRIVE, UINT8 CYL, UINT8 SIDE,
  1646.  
  1647. UINT8 SECTOR, UINT8 HUGE *BUFFER){$7b}
  1648.  
  1649. STATIC RESULTsTRING rs;
  1650.  
  1651.  
  1652.  
  1653. #IFDEF use_tsc
  1654.  
  1655. FPRINTF(STDERR,"%20S","VERIFYcbmSECTOR");
  1656.  
  1657. PRINT_tZ_SINCE();
  1658.  
  1659. #ENDIF
  1660.  
  1661.  
  1662.  
  1663.    // lET THE fdc crc CHECK THE WRITTEN DATA
  1664.  
  1665.       // "rEAL" COMPARISON CANNOT BE DONE
  1666.  
  1667.  
  1668.  
  1669. PREFILL9CMD();// FILL UP BYTES 5 TO 8
  1670.  
  1671.    fdcCOMMANDsTRING[0]=(fdPRM.mODULATION<<6) {$7c} 0X06;
  1672.  
  1673.    fdcCOMMANDsTRING[1]=((({$7e}SIDE)&1)<<2) {$7c} DRIVE;
  1674.  
  1675.    fdcCOMMANDsTRING[2]=CYL;
  1676.  
  1677.    fdcCOMMANDsTRING[3]=SIDE;
  1678.  
  1679.    fdcCOMMANDsTRING[4]=SECTOR;
  1680.  
  1681.  
  1682.  
  1683.    rs.d.st0=-2;// DEFAULT: fdc NOT RESPONDING
  1684.  
  1685. IF(ISSUEcMD(9,0X42,128U<<fdPRM.bPs,BUFFER) &&
  1686.  
  1687. VALID7rESULTsTRING(&rs)
  1688.  
  1689. )RETURN null;
  1690.  
  1691.    ELSE RETURN &rs;
  1692.  
  1693. {$7d}
  1694.  
  1695.  
  1696.  
  1697. // READ A TRACK WITH THE MULTIPLE SECTOR READING FEATURE OF THE fdc
  1698.  
  1699. //
  1700.  
  1701. // INPUT:  DRIVE:        THE DRIVE TO READ FROM
  1702.  
  1703. //         CYL:          THE CYLINDER NUMBER TO READ FROM
  1704.  
  1705. //         SIDE:         THE DISK SIDE NUMBER TO READ FROM
  1706.  
  1707. //         BUFFER:       A POINTER TO A BUFFER TO READ THE DATA IN
  1708.  
  1709. // OUTPUT: RESULTsTRING: null  - OPERATION WAS SUCESSFUL
  1710.  
  1711. //                       OTHER - THE FILLED UP RESULT STRUCTURE
  1712.  
  1713. //
  1714.  
  1715. RESULTsTRING *READcbmTRACK(UINT8 DRIVE, UINT8 CYL, UINT8 SIDE,
  1716.  
  1717. UINT8 SECTOR, UINT8 HUGE *BUFFER){$7b}
  1718.  
  1719. STATIC RESULTsTRING rs;
  1720.  
  1721.  
  1722.  
  1723. #IFDEF use_tsc
  1724.  
  1725. FPRINTF(STDERR,"%20S","READcbmTRACK");
  1726.  
  1727. PRINT_tZ_SINCE();
  1728.  
  1729. #ENDIF
  1730.  
  1731.  
  1732.  
  1733. PREFILL9CMD();// FILL UP BYTES 5 TO 8
  1734.  
  1735.    fdcCOMMANDsTRING[0]=(fdPRM.mODULATION<<6) {$7c} 0X06;
  1736.  
  1737.    fdcCOMMANDsTRING[1]=((({$7e}SIDE)&1)<<2) {$7c} DRIVE;
  1738.  
  1739.    fdcCOMMANDsTRING[2]=CYL;
  1740.  
  1741.    fdcCOMMANDsTRING[3]=SIDE;
  1742.  
  1743.    fdcCOMMANDsTRING[4]=SECTOR;// START SECTOR TO READ
  1744.  
  1745.  
  1746.  
  1747.    rs.d.st0=-2;// DEFAULT: fdc NOT RESPONDING
  1748.  
  1749. IF(ISSUEcMD(9,0X46,(128U << fdPRM.bPs) * (fdPRM.sECTORS - SECTOR + 1),
  1750.  
  1751.  BUFFER + (128U << fdPRM.bPs) * (SECTOR - 1)) &&
  1752.  
  1753. VALID7rESULTsTRING(&rs)
  1754.  
  1755. ){$7b}// SECOND HALF OF THE TRACK WAS READ WITH SUCCESS
  1756.  
  1757.  
  1758.  
  1759. IF(SECTOR<=1) RETURN null;// WHOLE TRACK IS ALREADY IN
  1760.  
  1761. #IFDEF use_tsc
  1762.  
  1763. FPRINTF(STDERR,"%20S","READcbmTRACK");
  1764.  
  1765. PRINT_tZ_SINCE();
  1766.  
  1767. #ENDIF
  1768.  
  1769.    fdcCOMMANDsTRING[4]=1;// BEGIN WITH THE FIRST HALF OF THE TRACK
  1770.  
  1771.  
  1772.  
  1773.       rs.d.st0=-2;// DEFAULT: fdc NOT RESPONDING
  1774.  
  1775.    IF(ISSUEcMD(9,0X46,(128U << fdPRM.bPs) * (SECTOR - 1),BUFFER) &&
  1776.  
  1777.    VALID7rESULTsTRING(&rs)
  1778.  
  1779. )RETURN null;// FIRST HALF OF TRACK WAS READ WITH SUCCESS
  1780.  
  1781. {$7d}
  1782.  
  1783.    RETURN &rs;// ERROR
  1784.  
  1785. {$7d}
  1786.  
  1787.  
  1788.  
  1789. // WRITE A TRACK WITH THE MULTIPLE SECTOR READING FEATURE OF THE fdc
  1790.  
  1791. //
  1792.  
  1793. // INPUT:  DRIVE:        THE DRIVE TO WRITE TO
  1794.  
  1795. //         CYL:          THE CYLINDER NUMBER TO WRITE TO
  1796.  
  1797. //         SIDE:         THE DISK SIDE NUMBER TO WRITE TO
  1798.  
  1799. //         BUFFER:       A POINTER TO A BUFFER TO WRITE THE DATA FROM
  1800.  
  1801. // OUTPUT: RESULTsTRING: null  - OPERATION WAS SUCESSFUL
  1802.  
  1803. //                       OTHER - THE FILLED UP RESULT STRUCTURE
  1804.  
  1805. //
  1806.  
  1807. RESULTsTRING *WRITEcbmTRACK(UINT8 DRIVE, UINT8 CYL, UINT8 SIDE,
  1808.  
  1809.  UINT8 SECTOR, UINT8 HUGE *BUFFER){$7b}
  1810.  
  1811. STATIC RESULTsTRING rs;
  1812.  
  1813.  
  1814.  
  1815. #IFDEF use_tsc
  1816.  
  1817. FPRINTF(STDERR,"%20S","WRITEcbmTRACK");
  1818.  
  1819. PRINT_tZ_SINCE();
  1820.  
  1821. #ENDIF
  1822.  
  1823.  
  1824.  
  1825. PREFILL9CMD();// FILL UP BYTES 5 TO 8
  1826.  
  1827.    fdcCOMMANDsTRING[0]=(fdPRM.mODULATION<<6) {$7c} 0X05;
  1828.  
  1829.    fdcCOMMANDsTRING[1]=((({$7e}SIDE)&1)<<2) {$7c} DRIVE;
  1830.  
  1831.    fdcCOMMANDsTRING[2]=CYL;
  1832.  
  1833.    fdcCOMMANDsTRING[3]=SIDE;
  1834.  
  1835.    fdcCOMMANDsTRING[4]=SECTOR;// START SECTOR TO READ
  1836.  
  1837.  
  1838.  
  1839.    rs.d.st0=-2;// DEFAULT: fdc NOT RESPONDING
  1840.  
  1841. IF(ISSUEcMD(9,0X4a,(128U << fdPRM.bPs) * (fdPRM.sECTORS - SECTOR + 1),
  1842.  
  1843.  BUFFER + (128U << fdPRM.bPs) * (SECTOR - 1)) &&
  1844.  
  1845. VALID7rESULTsTRING(&rs)
  1846.  
  1847. ){$7b}// SECOND HALF OF THE TRACK WAS READ WITH SUCCESS
  1848.  
  1849. IF(SECTOR<=1) RETURN null;// WHOLE TRACK IS ALREADY IN
  1850.  
  1851. #IFDEF use_tsc
  1852.  
  1853. FPRINTF(STDERR,"%20S","WRITEcbmTRACK");
  1854.  
  1855. PRINT_tZ_SINCE();
  1856.  
  1857. #ENDIF
  1858.  
  1859.    fdcCOMMANDsTRING[4]=1;// BEGIN WITH THE FIRST HALF OF THE TRACK
  1860.  
  1861.  
  1862.  
  1863.       rs.d.st0=-2;// DEFAULT: fdc NOT RESPONDING
  1864.  
  1865.    IF(ISSUEcMD(9,0X4a,(128U << fdPRM.bPs) * (SECTOR - 1),BUFFER) &&
  1866.  
  1867.    VALID7rESULTsTRING(&rs)
  1868.  
  1869. ){$7b}
  1870.  
  1871. RETURN null;// FIRST HALF OF TRACK WAS READ WITH SUCCESS
  1872.  
  1873.          {$7d}
  1874.  
  1875. {$7d}
  1876.  
  1877.    RETURN &rs;// ERROR
  1878.  
  1879. {$7d}
  1880.  
  1881.  
  1882.  
  1883. // VERIFY A TRACK WITH THE MULTIPLE SECTOR READING FEATURE OF THE fdc
  1884.  
  1885. //
  1886.  
  1887. // INPUT:  DRIVE:        THE DRIVE TO READ FROM
  1888.  
  1889. //         CYL:          THE CYLINDER NUMBER TO READ FROM
  1890.  
  1891. //         SIDE:         THE DISK SIDE NUMBER TO READ FROM
  1892.  
  1893. //         BUFFER:       A POINTER TO A BUFFER TO READ THE DATA IN
  1894.  
  1895. // OUTPUT: RESULTsTRING: null  - OPERATION WAS SUCESSFUL
  1896.  
  1897. //                       OTHER - THE FILLED UP RESULT STRUCTURE
  1898.  
  1899. //
  1900.  
  1901. RESULTsTRING *VERIFYcbmTRACK(UINT8 DRIVE, UINT8 CYL, UINT8 SIDE,
  1902.  
  1903.   UINT8 SECTOR, UINT8 HUGE *BUFFER){$7b}
  1904.  
  1905. STATIC RESULTsTRING rs;
  1906.  
  1907.  
  1908.  
  1909. #IFDEF use_tsc
  1910.  
  1911. FPRINTF(STDERR,"%20S","VERIFYcbmTRACK");
  1912.  
  1913. PRINT_tZ_SINCE();
  1914.  
  1915. #ENDIF
  1916.  
  1917.    // lET THE fdc crc CHECK THE WRITTEN DATA
  1918.  
  1919.       // "rEAL" COMPARISON CANNOT BE DONE
  1920.  
  1921.  
  1922.  
  1923. PREFILL9CMD();// FILL UP BYTES 5 TO 8
  1924.  
  1925.    fdcCOMMANDsTRING[0]=(fdPRM.mODULATION<<6) {$7c} 0X06;
  1926.  
  1927.    fdcCOMMANDsTRING[1]=((({$7e}SIDE)&1)<<2) {$7c} DRIVE;
  1928.  
  1929.    fdcCOMMANDsTRING[2]=CYL;
  1930.  
  1931.    fdcCOMMANDsTRING[3]=SIDE;
  1932.  
  1933.    fdcCOMMANDsTRING[4]=SECTOR;// START SECTOR TO READ
  1934.  
  1935.  
  1936.  
  1937.    rs.d.st0=-2;// DEFAULT: fdc NOT RESPONDING
  1938.  
  1939. IF(ISSUEcMD(9,0X42,(128U << fdPRM.bPs) * (fdPRM.sECTORS - SECTOR + 1),
  1940.  
  1941.  BUFFER + (128U << fdPRM.bPs) * (SECTOR - 1)) &&
  1942.  
  1943. VALID7rESULTsTRING(&rs)
  1944.  
  1945. ){$7b}// SECOND HALF OF THE TRACK WAS READ WITH SUCCESS
  1946.  
  1947. IF(SECTOR<=1) RETURN null;// WHOLE TRACK IS ALREADY IN
  1948.  
  1949. #IFDEF use_tsc
  1950.  
  1951. FPRINTF(STDERR,"%20S","VERIFYcbmTRACK");
  1952.  
  1953. PRINT_tZ_SINCE();
  1954.  
  1955. #ENDIF
  1956.  
  1957.    fdcCOMMANDsTRING[4]=1;// BEGIN WITH THE FIRST HALF OF THE TRACK
  1958.  
  1959.  
  1960.  
  1961.       rs.d.st0=-2;// DEFAULT: fdc NOT RESPONDING
  1962.  
  1963.    IF(ISSUEcMD(9,0X42,(128U << fdPRM.bPs) * (SECTOR - 1),BUFFER) &&
  1964.  
  1965. VALID7rESULTsTRING(&rs)
  1966.  
  1967. )RETURN null;// FIRST HALF OF TRACK WAS READ WITH SUCCESS
  1968.  
  1969. {$7d}
  1970.  
  1971.    RETURN &rs;// ERROR
  1972.  
  1973. {$7d}
  1974.  
  1975.  
  1976.  
  1977. // CHECK IF WE ARE USING AN INTEL EXTENDED CONTROLLER 82078
  1978.  
  1979. //
  1980.  
  1981. // INPUT:  NONE
  1982.  
  1983. // OUTPUT:  -1 (<0)      TIMEOUT OR GENERAL ERROR
  1984.  
  1985. //          0            STANDARD nec {$e6}pd 765 COMPATIBLE CONTROLLER
  1986.  
  1987. //          0X01XX       EXTENDED CONTROLLER (XX - STEPPING RESULT)
  1988.  
  1989. //          0X02XX       82078 COMPATIBLE CONTROLLER (XX - STEPPING RESULT)
  1990.  
  1991. //          0X03XX       FULLY 82078 COMPATIBLE fdc (XX - STEPPING RESULT)
  1992.  
  1993. //
  1994.  
  1995. SHORT CHECK4INTELfdc(VOID){$7b}
  1996.  
  1997. SHORT RES;
  1998.  
  1999.  
  2000.  
  2001. #IFDEF use_tsc
  2002.  
  2003. FPRINTF(STDERR,"%20S","CHECK4INTELfdc");
  2004.  
  2005. PRINT_tZ_SINCE();
  2006.  
  2007. #ENDIF
  2008.  
  2009. IF(OUTfdc(0X10)<0) RETURN -1;// ISSUE VERSION COMMAND
  2010.  
  2011. IF((RES=INfdc())<0) RETURN -1;
  2012.  
  2013.    IF(RES==0X90){$7b}// THIS IS AN EXTENDED CONTROLLER
  2014.  
  2015.  
  2016.  
  2017. IF(OUTfdc(0X18)<0) RETURN -1;// ISSUE PART ID COMMAND
  2018.  
  2019. IF((RES=INfdc())<0) RETURN -1;
  2020.  
  2021.  
  2022.  
  2023.       IF(RES>=0X41 && RES<=0X5f){$7b}
  2024.  
  2025.       // DO SOME MORE INTEL fdc COMPATIBILITY TESTS
  2026.  
  2027.       IF(RES==0X41) RES{$7c}=0X0300;// ORIGINAL (FIRST STEPPING)
  2028.  
  2029.       ELSE          RES{$7c}=0X0200;
  2030.  
  2031.       {$7d}
  2032.  
  2033.       ELSE RES{$7c}=0X0100;
  2034.  
  2035.       RETURN RES;
  2036.  
  2037.    {$7d}
  2038.  
  2039.    ELSE RETURN 0X0000;
  2040.  
  2041.    {$7d}
  2042.  
  2043.  
  2044.  
  2045. // FORMAT'N'WRITE A TRACK (ONE SIDE OF A CYLINDER)
  2046.  
  2047. //
  2048.  
  2049. // INPUT:  DRIVE:        THE DRIVE TO FORMAT A TRACK AT
  2050.  
  2051. //         CYL:          THE CYLINDER NUMBER TO BE WRITTEN INTO THE HEADERS
  2052.  
  2053. //         SIDE:         THE DISK SIDE NUMBER TO BE WRITTEN INTO THE HEADERS
  2054.  
  2055. //         BUFFER:       A POINTER TO A BUFFER TO WRITE THE DATA FROM
  2056.  
  2057. // OUTPUT: RESULTsTRING: null  - OPERATION WAS SUCESSFUL
  2058.  
  2059. //                       OTHER - THE FILLED UP RESULT STRUCTURE
  2060.  
  2061. //
  2062.  
  2063. RESULTsTRING *FNWRITEcbmTRACK(UINT8 DRIVE, UINT8 CYL, UINT8 SIDE, UINT8 HUGE *BUFFER){$7b}
  2064.  
  2065. STATIC RESULTsTRING rs;
  2066.  
  2067. // 4 id BYTES PER SECTOR
  2068.  
  2069. UINT8 fNwbUFFER[mAXsECTORS * 4 + tRbUFsIZE];// mAXsECTORS AND tRbUFsIZE ARE DEFINED IN central.h
  2070.  
  2071. INTI,J,K,L;
  2072.  
  2073.  
  2074.  
  2075. #IFDEF use_tsc
  2076.  
  2077. FPRINTF(STDERR,"%20S","FNWRITEc1581TRACK");
  2078.  
  2079. PRINT_tZ_SINCE();
  2080.  
  2081. #ENDIF
  2082.  
  2083.  
  2084.  
  2085. FOR(I=J=K=0;I<fdPRM.sECTORS;){$7b}// FILL UP THE id BYTES AND ENCAPSULATED WRITE DATA
  2086.  
  2087.    I++;// START WITH SECTOR 1
  2088.  
  2089. fNwbUFFER[J++]=CYL;// CYLINDER DESCRIPTOR
  2090.  
  2091. fNwbUFFER[J++]=SIDE;// HEAD DESCRIPTOR
  2092.  
  2093. fNwbUFFER[J++]=I;// SECTOR nO.
  2094.  
  2095. fNwbUFFER[J++]=fdPRM.bPs;
  2096.  
  2097.       FOR(L=(128 << fdPRM.bPs);L>0;L--) fNwbUFFER[J++]=BUFFER[K++];
  2098.  
  2099. // DEBUG
  2100.  
  2101. //      FOR(L=(128 << fdPRM.bPs);L>0;L--) fNwbUFFER[J++]=K++;
  2102.  
  2103. {$7d}
  2104.  
  2105.  
  2106.  
  2107. // THIS COMES FROM THE LINUX FLOPPY DRIVER, PERHAPS THERE'S A TYPO
  2108.  
  2109. // IN THE INTEL 82078 DATA SHEET ABOUT THE FORMAT'N'WRITE COMMAND
  2110.  
  2111. //   fdcCOMMANDsTRING[0]=(fdPRM.mODULATION<<6) {$7c} 0Xaf;
  2112.  
  2113.  
  2114.  
  2115. // iT'S NO TYPO...
  2116.  
  2117.    fdcCOMMANDsTRING[0]=(fdPRM.mODULATION<<6) {$7c} 0Xad;
  2118.  
  2119.    fdcCOMMANDsTRING[1]=((({$7e}SIDE)&1)<<2) {$7c} DRIVE;
  2120.  
  2121.    fdcCOMMANDsTRING[2]=fdPRM.bPs;
  2122.  
  2123.    fdcCOMMANDsTRING[3]=fdPRM.sECTORS;
  2124.  
  2125.    fdcCOMMANDsTRING[4]=fdPRM.fMTgap;
  2126.  
  2127.    fdcCOMMANDsTRING[5]=fdPRM.pATTERN;
  2128.  
  2129.  
  2130.  
  2131. IF(!ISSUEcMD(6,0X4a,fdPRM.sECTORS*(4+(128 << fdPRM.bPs)),fNwbUFFER)){$7b}
  2132.  
  2133.    rs.d.st0=-2;// fdc NOT RESPONDING
  2134.  
  2135.       RETURN &rs;
  2136.  
  2137.    {$7d}
  2138.  
  2139.    ELSE{$7b}
  2140.  
  2141. RETURN VALID7rESULTsTRING(&rs)?null:&rs;
  2142.  
  2143.    {$7d}
  2144.  
  2145. {$7d}
  2146.  
  2147.