home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / diskutil / flip / twst.c < prev   
Encoding:
C/C++ Source or Header  |  1989-03-22  |  29.6 KB  |  943 lines

  1. /*
  2.  *        Megamax C inline ASM version of Twister.
  3.  *        Converted from AS68 format  dlm  12/14/86.
  4.  *        AS68 version by David Small before that date.
  5.  *        Used for the MegAMin HD backup program.
  6.  *
  7.  */
  8.  
  9. /* patched by colas for use with FLIP:
  10.  * add params:
  11.  *    flipped: 0= no, 1=use back as front (must be SS then)
  12.  *    endtrack: 80 for normal disks
  13.  *    starttrack: 0 normally
  14.  * outputs a '-' for each formatted cylinder (see  PUTCHAR comments)
  15.  * no more verify
  16.  */
  17.  
  18. /* routine that are callable from C are: */
  19. extern twister();
  20. extern confirm_abort();
  21. extern printf();
  22.  
  23. #include "osbind.h" 
  24. #include "stdio.h"
  25.  
  26. /* global variables */
  27. int thedisk, dblsided, sectoroffset;   /* input parameters */
  28. int flipped, endtrack, starttrack, keypress;     /* colas params */
  29. long buffer;
  30.  
  31. int badflag;                        /* bad sector error flag */
  32.  
  33. /* local variables */
  34. static int theside, thetrack, twistsectorno, sectorno, retrycnt,
  35.          cdev, ctrack, csect, cside, ccount, A7t, interlv,
  36.          virgin, def_error, curr_err;
  37. static long cdma, edma, tmpdma, saveA2;
  38. static int saveA0, saveA1, saveD0;
  39. /* now the defines (AS68 equ's) */
  40.  
  41. /*    tunable values */
  42. #define retries   2         /* default # of retries -1 */
  43. #define midretry  1         /* "middle" retry, when to reseek  */
  44. #define timeout   0x40000    /* short timeout, motor already on */
  45. #define ltimeout  0x60000    /* long timeout, to startup motor    */
  46.  
  47. /*    Floppy state variables in DSB: RAM usage */
  48. #define recal       0xff00     /* recalibrate flag             */
  49. #define dcurtrack 0         /* current track number            */
  50. #define dseekrt   dcurtrack+2 /* seek rate    */
  51. #define dsbsiz    dseekrt+2    /* size of a DSB    */
  52.  
  53. /* hardware equates */
  54. /* DMA chip        */
  55. #define diskctl    0xffff8604    /* disk controller data access */
  56. #define fifo        0xffff8606    /* DMA mode control / status     */
  57. #define dmahigh    0xffff8609    /* DMA base high             */
  58. #define dmamid     0xffff860b    /* DMA base mid             */
  59. #define dmalow     0xffff860d    /* DMA base low             */
  60.  
  61. /* 1170 select values    */
  62. #define cmdreg     0x80         /* select command register    */
  63. #define trkreg     0x82         /* select track register     */
  64. #define secreg     0x84         /* select sector register    */
  65. #define datareg    0x86         /* select data register        */
  66.  
  67. /* GI sound chip (drive a/b select lines and side select) */
  68. #define giselect    0xffff8800    /* (W) sound chip register select */
  69. #define giread     0xffff8800    /* (R) sound chip read data    */
  70. #define giwrite    0xffff8802    /* (W) sound chip write data    */
  71. #define giporta    0x0e         /* GI register # for i/o port A */
  72.  
  73. /* 68901 mfp chip */
  74. #define mfp        0xfffffa00    /* mfp base            */
  75. #define gpip        mfp+1        /* general purpose i/o        */
  76.  
  77. /* misc defines */
  78. #define seekrate 3
  79. #define dsb0      0xa06
  80. #define dsb1      0xa0a
  81. #define flock      0x43e
  82.  
  83. char *abort_message = "\n\007KEY PRESSED! CR/SP = continue, other abort:\n";
  84.  
  85. asm {        /* start of inline ASM */
  86.  
  87. /*
  88.  *    All the following is munged code from AS68 (that's why the
  89.  *    weird format).  The AS68 code was munged from the BIOS
  90.  *    source.  And most of this is from the FDC article in Start
  91.  *    issue number 3.
  92.  *
  93.  *    Anyway, we apologize for the mess, but heh it works.
  94.  *
  95.  *    Oh yes.  The labels are usually on nops, not empty lines.  Thats
  96.  *    because AS68 occasionally pukes on labels on empty lines.  And
  97.  *    I didn't take the time to remove them.  (Megamax doesn't care.)
  98.  *
  99.  */
  100.  
  101. ;****************************************************************
  102. ; Twister: Faster formatter (zipformat) hack.  MM version        *
  103. ; Copyright (c) 1986, 1987 START Magazine (as usual)            *
  104. ; Written by David Y. Small & Dan Moore                     *
  105. ;****************************************************************
  106. ;
  107. ;             Dedication:
  108. ;
  109. ;     For Bill The Cat: because he's twisted, too.
  110. ;                        
  111. ;****************************************************************
  112. ;
  113. ; code begins.
  114. ;
  115. ;  PASS ME THIS STUFF DAN! Then SHAVE! For God's sakes! What
  116. ; are you trying to do, look like Fidel Castro?
  117. ;
  118. ; And get SOME BEER in here okay? Sheesh!
  119. ;
  120. ; input integers (if coming from C):
  121. ;
  122. ; dblsided: 0000 or ffff
  123. ; thedisk: 0 = a, 1 = b
  124. ;*************************************************************
  125.  
  126.  
  127. ;********************************************************
  128. ; Frammatter        
  129. ;********************************************************
  130. twister:    move.l    A2, saveA2(A4)     ; everything else saved by the Supexec
  131.  
  132.        clr.w        badflag(A4)        ; assume no errors
  133. ;
  134. ;*** Init vars for formatting loop
  135. ;
  136.     move.w D0, saveD0(A4);
  137.     move.w starttrack(A4), D0    ;start at starttrack
  138.     move.w D0, thetrack(A4)
  139.     move.w saveD0(A4), D0    
  140. ;WAS       move.w  #0,thetrack(A4)     ; start at track 0
  141.  
  142.        move.w  #1,twistsectorno(A4) ; twister value
  143.                          
  144.     move.w A0, saveA0(A4)
  145.     move.w A1, saveA1(A4)
  146. trackloop: nop               ; comes here for subseq tracks
  147.     move.w saveA0(A4), A0
  148.     move.w saveA1(A4), A1
  149.  
  150. ;***** FRONT SIDE ***********
  151. ;**** Setup stack: .. based on read sec command, tweaked for frammat
  152.  
  153.        move.w  #0xe5e5,-(A7)    ; virgin data -- e5's work okay
  154.        move.l  #0x87654321,-(A7) ; magic # to make format work / fmt only
  155.        move.w  #1,-(A7)       ; sector interleave factor / fmt only
  156.        move.w  flipped(A4),-(A7)       ; ** side.w (relevant) / side: FRONT
  157.        move.w  thetrack(A4),-(A7)  ; ** track.w (relevant) / same
  158.        move.w  #10,-(A7)      ; sector.w (irrelevant) / sectors per track
  159.        move.w  thedisk(A4),-(A7)     ; ** device.w  (relevant) / same
  160.        move.l  #0,-(A7)       ; dummy.l (irreleveant) / same
  161.        move.l  buffer(A4),-(A7)    ; ** buffer address.l (relevant) / same
  162.        jsr     _flopfmt
  163.        adda.l  #24,A7          ; Fix stack.
  164.        cmpi.w  #0xffff, badflag(A4)   ; aborts on error
  165.        beq     gemexit
  166. ;****
  167. ; Jazz twistsectorno(A4). Look at what it ended up as; set it to
  168. ; the next track twist depending on that.
  169. ;
  170. ; It will end up as "+1" from the last sector formatted, because
  171. ; the formatter bumps it up.
  172. ;
  173.        cmpi.w  #1,twistsectorno(A4)        ; 0-1 transition
  174.        beq     fgoto1
  175.        cmpi.w  #9,twistsectorno(A4)        ; 1-2 transition
  176.        beq     fgoto2
  177.        cmpi.w  #7,twistsectorno(A4)        ; 2-3 transition
  178.        beq     fgoto3
  179.        cmpi.w  #5,twistsectorno(A4)        ; 3-4 transition
  180.        beq     fgoto4
  181.        cmpi.w  #3,twistsectorno(A4)        ; 4-0 transition
  182.        beq     fgoto0
  183.        
  184.        dc.b    0x4a
  185.        dc.b    0xfc              ; oops, die (illegal instruction)
  186. ;*****
  187. ; Really class coding, eh? Oh,well, it's easy and it works, which
  188. ; twelve other fancy ways of doing this *don't*.
  189. ;
  190. fgoto1: move.w  #0x9,twistsectorno(A4)        ; 9,a,1,2,3,4,5,6,7,8
  191.        bra     fkeepformatting
  192. fgoto2: move.w  #0x7,twistsectorno(A4)        ; 7,8,9,a,1,2,3,4,5,6
  193.        bra     fkeepformatting
  194. fgoto3: move.w  #0x5,twistsectorno(A4)        ; 5,6,7,8,9,a,1,2,3,4
  195.        bra     fkeepformatting
  196. fgoto4: move.w  #0x3,twistsectorno(A4)        ; 3,4,5,6,7,8,9,a,1,2
  197.        bra     fkeepformatting
  198. fgoto0: move.w  #0x1,twistsectorno(A4)        ; 1,2,3,4,5,6,7,8,9,a
  199.        bra     fkeepformatting
  200.        nop
  201. ;*****
  202. fkeepformatting: nop
  203. ;*****
  204. ; now, do a verify on those sectors.
  205. ;**** Setup stack: .. based on read sec command, tweaked for frammat
  206. ;
  207. ;     tst.w     sectoroffset(A4)    ; no verify if 11 to 20 sector
  208. ;     ; numbering
  209. ;     bne     nover1
  210. ;     
  211. ;     move.w  #0xa,-(A7)       ; count.w 2
  212. ;     move.w  flipped(A4),-(A7)       ; ** side.w (relevant) / side: FRONT 4
  213. ;     move.w  thetrack(A4),-(A7)  ; ** track.w (relevant) / same 6
  214. ;     move.w  #0x1,-(A7)       ; sector.w (relevant) / starting sector 8
  215. ;     move.w  thedisk(A4),-(A7)     ; ** device.w  (relevant) / same 0xa
  216. ;     move.l  #0,-(A7)       ; dummy.l (irreleveant) / same 0xe
  217. ;     move.l  buffer(A4),-(A7) ; ** buffer address.l (relevant) / same 0x12
  218. ;     
  219. ;     move.w  #19,-(A7)      ; do BIOS _flopver 0x14
  220. ;     trap     #14
  221. ;     adda.l  #20, A7         ; fix stack.
  222. ;     
  223. ;     tst.l     D0
  224. ;     bne     badsecs
  225. ;     
  226. ;****
  227.  
  228. ;***** BACK SIDE ******        (How kinky Dave.  What _are_ you talking about?)
  229.  
  230. nover1:    tst.w   dblsided(A4)
  231.         beq       nobackside
  232.  
  233. ;**** Setup stack: .. based on read sec command, tweaked for frammat
  234.  
  235.        move.w  #0xe5e5,-(A7)    ; virgin data -- e5's work okay
  236. ; and with a virgin.  My, you really are weird Dave.
  237.        move.l  #0x87654321,-(A7) ; magic # to make format work / fmt only
  238.        move.w  #1,-(A7)       ; sector interleave factor / fmt only
  239.        move.w  #1,-(A7)       ; ** side.w (relevant) / side: BACK
  240.        move.w  thetrack(A4),-(A7)  ; ** track.w (relevant) / same
  241.        move.w  #10,-(A7)      ; sector.w (irrelevant) / sectors per track
  242.        move.w  thedisk(A4),-(A7)     ; ** device.w  (relevant) / same
  243.        move.l  #0,-(A7)       ; dummy.l (irreleveant) / same
  244.        move.l  buffer(A4),-(A7)    ; ** buffer address.l (relevant) / same
  245.        jsr     _flopfmt
  246.        adda.l  #24,A7          ; Fix stack.
  247.        cmpi.w  #0xffff, badflag(A4)   ; aborts on error
  248.        beq     gemexit
  249. ;*****
  250. ;
  251. ; Jazz twistsectorno(A4). Look at what it ended up as; set it to
  252. ; the next track twist depending on that.
  253. ;
  254. ; It will end up as "+1" from the last sector formatted, because
  255. ; the formatter bumps it up.
  256. ;
  257.        cmpi.w  #1,twistsectorno(A4)        ; 0-1 transition
  258.        beq     goto1
  259.        cmpi.w  #9,twistsectorno(A4)        ; 1-2 transition
  260.        beq     goto2
  261.        cmpi.w  #7,twistsectorno(A4)        ; 2-3 transition
  262.        beq     goto3
  263.        cmpi.w  #5,twistsectorno(A4)        ; 3-4 transition
  264.        beq     goto4
  265.        cmpi.w  #3,twistsectorno(A4)        ; 4-0 transition
  266.        beq     goto0
  267.  
  268.        dc.b     0x4a
  269.        dc.b     0xfc              ; oops, die
  270.  
  271. ;
  272. goto1:  move.w  #0x9,twistsectorno(A4)        ; 9,a,1,2,3,4,5,6,7,8
  273.        bra     keepformatting
  274. goto2:  move.w  #0x7,twistsectorno(A4)        ; 7,8,9,a,1,2,3,4,5,6
  275.        bra     keepformatting
  276. goto3:  move.w  #0x5,twistsectorno(A4)        ; 5,6,7,8,9,a,1,2,3,4
  277.        bra     keepformatting
  278. goto4:  move.w  #0x3,twistsectorno(A4)        ; 3,4,5,6,7,8,9,a,1,2
  279.        bra     keepformatting
  280. goto0:  move.w  #0x1,twistsectorno(A4)        ; 1,2,3,4,5,6,7,8,9,a
  281.        bra     keepformatting
  282.        nop
  283. ;
  284. keepformatting: nop           ; entry after twisting.
  285. ;
  286. ;     
  287. ;     ;**** Setup stack: .. based on read sec command, tweaked for frammat
  288. ;     
  289. ;     tst.w     sectoroffset(A4) ; no verify for strange sector numbers
  290. ;     bne     nobackside
  291. ;     
  292. ;     move.w  #0xa,-(A7)       ; count.w 2
  293. ;     move.w  #1,-(A7)       ; ** side.w (relevant) / side: BACK 4
  294. ;     move.w  thetrack(A4),-(A7)  ; ** track.w (relevant) / same 6
  295. ;     move.w  #0x1,-(A7)       ; sector.w (relevant) / starting sector # 8
  296. ;     move.w  thedisk(A4),-(A7)     ; ** device.w  (relevant) / same 0xa
  297. ;     move.l  #0,-(A7)       ; dummy.l (irreleveant) / same 0xe
  298. ;     move.l  buffer(A4),-(A7) ; ** buffer address.l (relevant) / same 0x12
  299. ;     
  300. ;     move.w  #19,-(A7)      ; do BIOS _flopver 0x14 (why not)
  301. ;     trap     #14
  302. ;     adda.l  #20, A7          ; fix stack
  303. ;     
  304. ;     tst.l     D0
  305. ;     bne     badsecs          ; wham
  306. ;     
  307. ;****
  308. nobackside: nop      ; entry if not DS  (well at least this isn't kinky Dave)
  309.  
  310. ; add 1 to thetrack. If endtrack, quit.
  311.        addi.w   #1, thetrack(A4)
  312.     move.w A0, saveA0(A4)
  313.     move.w A1, saveA1(A4)
  314.  
  315.     move.w D0, saveD0(A4)        /* PUTCHAR */
  316.     move.w #0x2D, -(A7)        /* outputs a '-' */
  317.     move.w #6, -(A7)
  318.     trap #1
  319.     adda.l #4, A7
  320.     move.w #0xB, -(A7)        /* CNONIS */
  321.     trap #1
  322.     adda.l #2, A7
  323.     cmpi.w  #0,D0
  324.         bne key_pressed            /* aborts on keypress */
  325. resume:    move.w saveD0(A4), D0        /* PUTCHAR end */
  326.  
  327.     move.w endtrack(A4), A0
  328.     move.w thetrack(A4), A1
  329.     cmpa A0, A1
  330.        bne     trackloop      ; "do another"
  331.  
  332.     move.w saveA0(A4), A0
  333.     move.w saveA1(A4), A1
  334.        bra     gemexit          ; Continue, etc, and so forth
  335.  
  336. ;*********
  337. key_pressed:    
  338.     MOVE.w    #8,-(A7)
  339.     trap #1
  340.     ADDa.L    #2,A7
  341.     CMPI.w    #27,D0
  342.     beq    key_abort
  343.     move.l  abort_message(A4),-(A7)
  344.     move.w  #9,-(A7)
  345.     trap #1
  346.     ADDa.L    #6,A7
  347.     MOVE.w    #8,-(A7)
  348.     trap    #1
  349.     ADDa.L    #2,A7
  350.     CMPI.w    #32,D0
  351.     beq    resume
  352.     CMPI.w    #10,D0
  353.     beq    resume
  354.     CMPI.w    #13,D0
  355.     beq    resume
  356. key_abort:    MOVE.w    #1,keypress(A4)
  357.     move.w  saveD0(A4), D0
  358.     bra gemexit
  359.  
  360. ;*********
  361. badsecs:    move.w #0xffff, badflag(A4)  ; bad sectors found
  362.  
  363. ;**************
  364. ;
  365. ; End. Exit to calling routine.
  366. ;
  367. gemexit:    movea.l saveA2(A4), A2  ; only reg not saved by Supexec
  368.         rts
  369.  
  370. ;******************************************************
  371. ;
  372. ;------------------------------------------------------------------------
  373. ;       130-ST / 520-ST    
  374. ;       Floppy Disk Driver    
  375. ;       (C)1985 Atari Corp.    
  376. ;       From the FDC article (Start issue 3); shortened to just
  377. ;       the formatter routine and the low level I/O.        
  378. ;                                
  379. ;------------------------------------------------------------------------
  380. ;
  381. ;************************************************************
  382. ;
  383. ; _flopfmt - format a track
  384. ; Passed (on the stack):
  385. ;       0x1a(A7) initial sector data
  386. ;       0x16(A7) magic number
  387. ;       0x14(A7) interleave
  388. ;       0x12(A7) side
  389. ;       0x10(A7) track
  390. ;        0xe(A7) A7t(A4)
  391. ;        0xc(A7) drive
  392. ;        0x8(A7) pointer to state block
  393. ;        0x4(A7) dma address
  394. ;        0x0(A7) [return]
  395. ;
  396. ; Returns:     EQ: track successfully written.  Zero.W-terminated list of
  397. ;             bad sectors left in buffer (they might /all/ be bad.)
  398. ;
  399. ;             NE: could not write track (write-protected, drive 
  400. ;             failure, or something catastrophic happened).
  401. ;-
  402. _flopfmt:
  403.        cmpi.l   #0x87654321, 0x16(A7)        ; check for magic# on stack
  404.        bne     flopfail         ; no magic, so we just saved the world
  405. ;       bsr     change            ; check for disk flip
  406. ;       moveq     #e_error,D0        ; set default error number
  407.        bsr     floplock             ; lock floppies, setup parms
  408.        bsr     select                ; select drive and side
  409.        move.w  0xe(A7),A7t(A4)        ; save sectors-per-track
  410.        move.w  0x14(A7),interlv(A4)        ; save interleave factor
  411.        move.w  0x1a(A7),virgin(A4)        ; save initial sector data
  412.  
  413. ;--- put drive into "changed" mode
  414. ;       moveq     #m_changed,D0         ; D0 = "CHANGED"
  415. ;       bsr     setdmode             ; set media change mode
  416.  
  417. ;--- seek to track (hard seek):
  418. ;debug* move.l  #0xff00ff00,0xf8030
  419.        bsr     hseek                ; hard seek to 'ctrack'
  420. ;debug* move.l  #0x00000000,0xf8030
  421.        bne     flopfail             ; (return error on seek failure)
  422.        move.w  ctrack(A4),dcurtrack(A1)    ; record current track#
  423.  
  424. ;--- format track, then verify it:
  425. ;*       move.w  #e_error,curr_err(A4)(A5)   ; vanilla error mode
  426. ;debug* move.l  #0xff00ff00,0xfA030
  427.        bsr     fmtrack                ; format track
  428. ;debug* move.l  #0x0,0xfA030
  429.  
  430.        bne     flopfail             ; (return error on seek failure)
  431.        bra     flopok
  432.  
  433.  
  434. ;****************************
  435. ;+
  436. ; fmtrack - format a track. Tweaked for skewed interleave.
  437. ;
  438. ; Passed:      variables setup by _flopfmt
  439. ; Returns:     NE on failure, EQ on success
  440. ; Uses:         almost everything
  441. ; Called-by:     _flopfmt
  442. ;
  443. ;-
  444. fmtrack:
  445. ;*       move.w  #e_write,def_error(A4)    ; set default error number
  446.        move.w  #1,D3        ; start with sector 1, first pass
  447. ;**
  448.        movea.l  cdma(A4),A2            ; A2 =  prototyping area
  449. ; Lay down beginning of track
  450.  
  451.        move.w  #60-1,D1             ; 60 x 0x4e (track leadin)
  452.        move.b  #0x4e,D0
  453.        bsr     wmult
  454. ; Repeat 10 times: sector data.
  455.        move.w  #1,sectorno(A4)            ; how many secs written
  456. ; Note that twistsectorno is initialized out of this routine.
  457. ;--- address mark
  458. secloop: nop
  459. ;
  460. ot1:    move.w  #12-1,D1             ; 12 x 0x00
  461.        clr.b     D0
  462.        bsr     wmult
  463.        move.w  #3-1,D1                ; 3 x 0xf5
  464.        move.b  #0xf5,D0
  465.        bsr     wmult
  466.        move.b  #0xfe,(A2)+             ; 0xfe -- address mark intro
  467.        move.b  ctrack+1(A4),(A2)+         ; track# - low half of word
  468.        move.b  cside+1(A4),(A2)+            ; side# - low half of word
  469.  
  470. ;* #1: just use a plain sector number
  471. ;*       move.b  D4,(A2)+             ; sector#
  472.  
  473. ;* #2: use a twisted sector number
  474. ;*       move.b  twistsectorno+1(A4),(A2)+   ; new: sector #.
  475.  
  476.        move.w  twistsectorno(A4),D0        ; fetch     1-10 sector #
  477. ;
  478. ; Note that meg-a-minute backup uses sectors # 11-20 to force GEM
  479. ; not to use MM disks.
  480. ;
  481.        add.w   sectoroffset(A4),D0    ; add possible shift to 11-20 sector #
  482.        move.b  D0,(A2)+             ; plug it into sector table
  483.  
  484. ; Add 1 to sector #. If it is b, wrap it to 1.
  485.        addi.w  #1,twistsectorno(A4)        ; real sector # being plopped
  486.        cmpi.w  #0xb,twistsectorno(A4)
  487.        bne     notb
  488.        move.w  #1,twistsectorno(A4)
  489. ;
  490. notb:   nop
  491.        move.b  #0x02,(A2)+             ; sector size (512)
  492.        move.b  #0xf7,(A2)+             ; write checksum
  493.  
  494. ;--- gap between AM and data:
  495.        move.w  #22-1,D1             ; 22 x 0x4e
  496.        move.b  #0x4e,D0
  497.        bsr     wmult
  498.        move.w  #12-1,D1             ; 12 x 0x00
  499.        clr.b     D0
  500.        bsr     wmult
  501.        move.w  #3-1,D1                ; 3 x 0xf5
  502.        move.b  #0xf5,D0
  503.        bsr     wmult
  504.  
  505. ;--- data block:
  506.        move.b  #0xfb,(A2)+             ; 0xfb -- data intro
  507.        move.w  #256-1,D1        ; 256 x virgin.w (initial sector data)
  508. ot2:    move.b  virgin(A4),(A2)+            ; copy high byte
  509.        move.b  virgin+1(A4),(A2)+         ; copy low byte
  510.        dbf     D1,ot2                ; fill 512 bytes
  511.        move.b  #0xf7,(A2)+             ; 0xf7 -- write checksum
  512.        move.w  #40-1,D1             ; 40 x 0x4e
  513.        move.b  #0x4e,D0
  514.        bsr     wmult
  515. ;
  516. ; Next sector, or, end-of-track. If we hit sector 11, time to quit.
  517. ;
  518.        addi.w   #1,sectorno(A4)
  519.        cmpi.w  #11,sectorno(A4)
  520.        bne     secloop          ; loop again
  521. ;
  522. ; Okay, 10 sectors laid down. 
  523. ;
  524. ;--- end-of-track
  525.        move.w  #1400,D1         ; 1401 x 0x4e -- end of track trailer
  526.        move.b  #0x4e,D0
  527.        bsr     wmult
  528.  
  529. ;--- setup to write the track:
  530.        move.b  cdma+3(A4),dmalow     ; load dma pointer
  531.        move.b  cdma+2(A4),dmamid
  532.        move.b  cdma+1(A4),dmahigh
  533.        move.w  #0x190,(A6)             ; toggle R/W flag and
  534.        move.w  #0x090,(A6)             ; select sector-count register
  535.        move.w  #0x190,(A6)
  536.        move.w  #0x1f,D7              ; (absurd sector count)
  537.        bsr     wdiskctl
  538.        move.w  #0x180,(A6)             ; select 1770 cmd register
  539.        move.w  #0xf0,D7              ; write format_track command
  540. ;debug* move.l  #0xff00ff00,0xfc030
  541.        bsr     wdiskctl
  542.        move.l  #timeout,D7            ; D7 = timeout value
  543.  
  544. ;--- wait for 1770 to complete:
  545. otw1:   btst.b  #5,gpip                ; is 1770 done?
  546.        beq     otw2                ; (yes)
  547.        subq.l  #1,D7                ; if(--D7) continue;
  548.        bne     otw1
  549. ;debug* move.l  #0xffffffff,0xfc030
  550.  
  551.        bsr     reset1770            ; timed out -- reset 1770
  552. oterr:  moveq     #1,D7                ; return NE (error status)
  553.        rts
  554.  
  555. ;--- see if the write-track won:
  556. otw2:   nop
  557. ;debug* move.l  #0x0,0xfc030
  558.  
  559.        move.w  #0x190,(A6)             ; check DMA status bit
  560.        move.w  (A6),D0
  561.        btst     #0,D0            ; if its zero, there was a DMA error
  562.        beq     oterr                ; (so return NE)
  563.        move.w  #0x180,(A6)             ; get 1770 status
  564.        bsr     rdiskctl
  565. ;**       bsr     err_bits             ; set 1770 error bits
  566.        and.b     #0x44,D0     ; check for writeProtect & lostData
  567.        rts                ; return NE on 1770 error
  568.  
  569. ;------ write 'D1+1' copies of D0.B into A2, A2+1, ...
  570. wmult:  move.b  D0,(A2)+             ; record byte in proto buffer
  571.        dbf     D1,wmult             ; (do it again)
  572.        rts
  573. ;
  574. ;************************************************************
  575. ;
  576. ; floplock - lock floppies and setup floppy parameters
  577. ;
  578. ; Passed (on the stack):
  579. ;       0x18(A7) - count.W (sector count)
  580. ;       0x16(A7) - side.W (side#)
  581. ;       0x14(A7) - track.W (track#)
  582. ;       0x12(A7) - sect.W (sector#)
  583. ;       0x10(A7) - dev.W (device#)
  584. ;        0xc(A7) - obsolete.L
  585. ;        8(A7) - dma.L (dma pointer)
  586. ;        4(A7) - ret1.L (caller's return address)
  587. ;        0(A7) - ret.L (floplock's return address)
  588. ;
  589. ; It is not coincidence that this matches the read and write input list;
  590. ; they call us to get stuff off stack and plug into parameters. Then,
  591. ; routine "select" actually pops this stuff into hardware.
  592. ;
  593. ; Passed:      D0.W = default error number
  594. ;
  595. ; Also, we helpfully point A6 at the DMA chip, and A1 at the DSB.
  596. ;-
  597. floplock:
  598.        lea    regsave, A0
  599.        movem.l D3-D7/A3-A6, (A0)        ; save C registers
  600.        lea     fifo,A6                ; A6 -> fifo
  601. ; Start setting up param block..
  602.        move.w  D0,def_error(A4)            ; set default error number
  603.        move.w  D0,curr_err(A4)            ; set current error number
  604. ; Kick VBL off floppies..
  605.        move.w  #1,flock             ; tell vbl not to touch floppies
  606. ; Stuff off stack:
  607.        move.l  8(A7),cdma(A4)            ; cdma -> /even/ DMA address
  608.        move.w  0x10(A7),cdev(A4)      ; save device# (0 .. 1)
  609.        move.w  0x12(A7),csect(A4)   ; save sector# (1 .. 9, usually)
  610.        move.w  0x14(A7),ctrack(A4)  ; save track# (0 .. 39 .. 79 ..)
  611.        move.w  0x16(A7),cside(A4)   ; save side# (0 .. 1)
  612.        move.w  0x18(A7),ccount(A4)  ; save sector count (1..A)
  613. ;--- pick a DSB: Point A1 at it.
  614.        lea     dsb0,A1          ; pick dsb 0 (drive A)
  615.        tst.w     cdev(A4)
  616.        beq     flock2
  617.        lea     dsb1,A1          ; pick dsb 1 (drive B)
  618. ;--- compute ending DMA address from count parameter: Plug into edma.
  619. ; This is used in multisector transfers in read-multiple-sector,
  620. ; but we don't use it here.
  621. flock2: moveq     #0,D7
  622.        move.w  ccount(A4),D7             ; edma = cdma + (ccount * 512)
  623.        lsl.w     #8,D7
  624.        lsl.w     #1,D7                ; do a 9 shift..
  625.        movea.l  cdma(A4),A0
  626.        adda.l   D7,A0
  627.        move.l  A0,edma(A4)                ; save in edma
  628. ;--- recalibrate drive, if it needs it. This only happens when the DSB
  629. ; says that this drive has never awoken before, and needs an initial
  630. ; recal to match its current track # with the DSB track #. 
  631.        tst.w     dcurtrack(A1)         ; if (curtrack < 0) recalibrate()
  632.        bpl     flockr
  633. ; RECAL needed. Show flag about it..
  634.        move.l  #0xf0f0f0f0,0xfe000
  635.        move.l  #0xf0f0f0f0,0xfe004
  636.  
  637.        bsr     select                ; select drive & side
  638.        clr.w     dcurtrack(A1)         ; we're optimistic -- assume winnage
  639. ; Restore.
  640.        bsr     restore                ; attempt restore
  641.        beq     flockr                ; (it won)
  642.        moveq     #10,D7                ; attempt seek to track 10
  643.        bsr     hseek1
  644.        bne     flock1                ; (failed)
  645.        bsr     restore                ; attempt restore again
  646.        beq     flockr                ; (it won)
  647. ;
  648. flock1:  move.w  #recal, dcurtrack(A1)      ; complete failure (what can we do?)
  649.  
  650.        movem.l regsave(PC), D3-D7/A3-A6
  651. flockr: rts
  652. ;
  653. ;********************************************************************
  654. ;+
  655. ; flopfail - unlock floppies and return error.
  656. ; Common way for read and write to return.
  657. ;
  658. ; Note: Returns via unlok1.
  659. ;-
  660. flopfail:
  661.        move.w #0xffff, badflag(A4)           ; bad sectors found
  662.        move.l  #0xffffffff,D0         ; aargh, error
  663.        bra   unlok1
  664.  
  665. ;***************************************************
  666. ;+
  667. ; flopok - unlock floppies and return success status. Also a common
  668. ; way for r/w to return.
  669. ;
  670. ;-
  671. flopok: clr.l     D0                    ; return 0 (success)
  672. ; Entry point from flopfail..
  673. unlok1: move.l  D0,-(A7)             ; (save return value)
  674. ; I believe this code returns the FDC's status to a type-1 status, where
  675. ; the write protect switch is available for VBL to look at.
  676.        move.w  #datareg,(A6)         ; force WP to real-time mode
  677. ; Sets FDC's current track register to track we are on right now.
  678.        move.w  dcurtrack(A1),D7        ; dest-track = current track
  679.        bsr     wdiskctl
  680. ; Does it with a "noop seek" (source=dest). Only forces FDC to type 1 status.
  681.        move.w  #0x10,D6              ; cmd = seek w/o verify
  682.        bsr     flopcmds             ; do it
  683. ;
  684. unlok2: move.l  (A7)+,D0             ; restore return value
  685.        movem.l  regsave(PC), D3-D7/A3-A6
  686. ; clear floppy lock of vblank..
  687.        clr.w     flock        ; allow vblank .. unlock floppies
  688. ; wave byebye at the pretty camera, jenny...
  689.        rts
  690. ;************************ Seek routines ********************
  691. ;+
  692. ; hseek  - seek to 'ctrack(A4)' without verify
  693. ; hseek1 - seek to 'D7' without verify
  694. ; hseek2 - seek to 'D7' without verify, keep current error number
  695. ;
  696. ; Returns:     NE on seek failure ("cannot happen"?)
  697. ;             EQ if seek wins
  698. ;
  699. ; Uses:         D7, D6, ...
  700. ; Exits to:     flopcmds
  701. ; Called-by:     _flopfmt, _flopini
  702. ;
  703. ;-
  704. hseek:  move.w  ctrack(A4),D7             ; dest track = 'ctrack'
  705. hseek1: nop
  706. hseek2: move.w  #datareg,(A6)         ; write destination track# to data reg
  707.        bsr     wdiskctl             ; write D7 to FDC data register
  708. ; seek command:
  709.        move.w  #0x10,D6              ; execute "seek" command
  710. ;                                * Note: no spinup time.
  711.        bra     flopcmds             ; (without verify...)
  712. ;
  713. ;***********************************************
  714. ;+
  715. ; reseek - home head, then reseek track
  716. ; Returns:     EQ/NE on success/failure
  717. ; Falls-into:     go2track
  718. ;
  719. ;-
  720. reseek:
  721.        bsr     restore                ; restore head
  722.        bne     go2trr                ; (punt if home fails)
  723.  
  724.        clr.w     dcurtrack(A1)         ; current track = 0
  725.        move.w  #trkreg,(A6)            ; set "current track" reg on 1770
  726.        clr.w     D7
  727.        bsr     wdiskctl             ; write a 00 to trk register.
  728.  
  729.        move.w  #datareg,(A6)         ; seek out to track five
  730.        move.w  #5,D7
  731.        bsr     wdiskctl             ; dest track = 5
  732.        move.w  #0x10,D6
  733.        bsr     flopcmds             ; seek
  734. ;                                * Note: no spinup time.
  735.        bne     go2trr                ; return error on seek failure
  736.        move.w  #5,dcurtrack(A1)        ; set current track#
  737.  
  738. ;***********************************************+
  739. ; go2track - seek proper track
  740. ; Passed:      Current floppy parameters (ctrack, et al.).
  741. ; Returns:     EQ/NE on success/failure
  742. ; Calls:         flopcmds
  743. ; Called by: read sector, for instance. Lots of places.
  744. ;-
  745. go2track:
  746.        move.w  #datareg,(A6)         ; set destination track# in
  747.        move.w  ctrack(A4),D7             ;  1770's data register
  748.        bsr     wdiskctl             ; (write track#)
  749.        moveq     #0x14,D6              ; execute 1770 "seek_with_verify"
  750.        bsr     flopcmds             ; (include seek-rate bits)
  751.        bne     go2trr                ; return error on seek failure
  752.        move.w  ctrack(A4),dcurtrack(A1)    ; update current track number
  753.        and.b     #0x18,D7              ; check for RNF, CRC_error, lost_data
  754. go2trr: rts                        ; return EQ/NE on succes/failure
  755.  
  756. ;*************************************************
  757. ;+
  758. ; restore - home head
  759. ; Passed:      nothing
  760. ; Returns:     EQ/NE on success/failure
  761. ;-
  762. restore:
  763.        clr.w     D6                    ; 0x00 = 1770 "restore" command
  764.        bsr     flopcmds             ; do restore
  765.        bne     res_r                ; punt on timeout
  766.        btst     #2,D7                ; test TRK00 bit
  767.        eori.w  #0x04, CCR            ; flip Z bit (return NE if bit is zero)
  768.        bne     res_r                ; punt if didn't win
  769.        clr.w     dcurtrack(A1)         ; set current track#
  770. res_r:  rts
  771.  
  772. ;****************************************************
  773. ; Special floppy cmd just for seeking:
  774. ;+
  775. ; flopcmds - floppy command (or-in seek speed bits from database)
  776. ; Passed:      D6.w = 1770 command
  777. ; Sets-up:     seek bits (bits 0 and 1) in D6.w
  778. ; Falls-into:     flopcmd
  779. ; Returns:     EQ/NE on success/failure
  780. ;
  781. ; I get the impression this is only used for seeking. I am right.
  782. ;-
  783. flopcmds:
  784.        move.w  dseekrt(A1),D0        ; get floppy's seek rate bits
  785.        andi.b  #3,D0                ; OR into command
  786.        or.b     D0,D6
  787. ; Fall in...
  788. ;******************************************************+
  789. ; flopcmd - execute any ol' 1770 command (with timeout)
  790. ; Passed:      D6.w = 1770 command
  791. ;
  792. ; Returns:     EQ/NE on success/failure
  793. ;             D7 = 1770 status bits
  794. ;
  795. ; Note: does motor spinup, if cmd in D6 specs it (I would *hope*!)
  796. ;-
  797. flopcmd:
  798.        move.l  #timeout,D7            ; setup timeout count (assume short)
  799.        move.w  #cmdreg,(A6)            ; select 1770 command register
  800.        bsr     rdiskctl             ; read it to clobber READY status
  801.        btst     #7,D0                ; is motor on?
  802.        bne     flopcm                ; (yes, keep short timeout)
  803.        move.l  #ltimeout,D7            ; extra timeout for motor startup
  804. flopcm: bsr     wdiskct6             ; write command (in D6)
  805.  
  806. flopc1: subq.l  #1,D7                ; timeout?
  807.        beq     flopcto                ; (yes, reset and return failure)
  808.        btst.b  #5,gpip                ; 1770 completion?
  809.        bne     flopc1                ; (not yet, so wait some more)
  810.        bsr     rdiskct7             ; return EQ + 1770 status in D7
  811.        clr.w     D6
  812.        rts
  813. ;****
  814. flopcto:
  815. ; We timed out.. a gruesome death indeed.
  816. ; Whap controller back to life.    (Hit him harder Dave, he likes it that way)
  817.        bsr     reset1770            ; bash controller
  818.        moveq     #1,D6                ; and return NE
  819.        rts
  820.  
  821. ;*******************************************************
  822. ;+
  823. ; reset1770 - reset disk controller after a catastrophe
  824. ; Passed:      nothing
  825. ; Returns:     nothing
  826. ; Uses:         D7
  827. ;-
  828. reset1770:
  829.        move.w  #cmdreg,(A6)            ; execute 1770 "reset" command
  830.        move.w  #0xD0,D7              ; force interrupt
  831.        bsr     wdiskctl
  832.        move.w  #15,D7                ; wait for 1770 to stop convulsing
  833. r1770:  dbf     D7,r1770             ; (short delay loop)
  834.        bsr     rdiskct7             ; return 1770 status in D7
  835.        rts
  836.  
  837. ;******************************************************
  838. ;+
  839. ; select - setup drive select, 1770 and DMA registers
  840. ; Passed:      cside(A4), cdev(A4)
  841. ; Returns:     appropriate drive and side selected
  842. ;
  843. ; Called: All over the place.
  844. ;
  845. ;-
  846. select: move.w  #0,0x9c0              ; floppies NOT deselected
  847. ;                                * lets VBL shut them off...
  848.        move.w  cdev(A4),D0                ; get device number
  849.        addq.b  #1,D0                ; add and shift to get select bits
  850.        lsl.b     #1,D0                ; into bits 1 and 2
  851.        or.w     cside(A4),D0                ; or-in side number (bit 0)
  852.        eori.b   #7,D0                 ; negate bits for funky hardware select
  853.        andi.b   #7,D0                 ; strip anything else out there
  854.        bsr     setporta             ; do drive select
  855. ; Have to restore 1770's track register from table..in dsb.
  856.        move.w  #trkreg,(A6)            ; setup 1770 track register
  857.        move.w  dcurtrack(A1),D7        ; from current track number
  858.        bsr     wdiskctl
  859.        clr.b     tmpdma(A4)                ; zero bits 24..32 of target DMA addr
  860.  
  861. ; Setup R/W parameters on 1770. Used by
  862. ; r/w sector, among others. This is where the sector register gets set.
  863. select1:
  864.        move.w  #secreg,(A6)            ; setup requested sector_number from
  865.        move.w  csect(A4),D7                ;      caller's parameters
  866.        bsr     wdiskctl
  867.        move.b  cdma+3(A4),dmalow            ; setup DMA chip's DMA pointer
  868.        move.b  cdma+2(A4),dmamid
  869.        move.b  cdma+1(A4),dmahigh
  870.        rts
  871.  
  872. ;************************************************
  873. ;+
  874. ; setporta - set floppy select bits in PORT A on the sound chip
  875. ; Passed:      D0.b (low three bits)
  876. ; Returns:     D1 = value written to port A
  877. ;             D2 = old value read from port A
  878. ; Uses:         D1
  879. ;-
  880. setporta:
  881.        move     SR,-(A7)             ; save our IPL
  882.        ori     #0x0700,SR             ; start critical section
  883.        move.b  #giporta,giselect        ; select port on GI chip
  884.        move.b  giread,D1            ; get current bits
  885.        move.b  D1,D2                ; save old bits for caller
  886.        andi.b   #0xff-7,D1              ; strip low three bits there
  887.        or.b     D0,D1                ; or-in our new bits
  888.        move.b  D1,giwrite            ; and write 'em back out there
  889.        move     (A7)+,SR             ; restore IPL to terminate CS, return
  890.        rts
  891.  
  892. ;**************************************************
  893. ;+
  894. ; Primitives to read/write 1770 controller chip (DISKCTL register).
  895. ;
  896. ; The 1770 can't keep up with full-tilt CPU accesses, so
  897. ; we have to surround reads and writes with delay loops.
  898. ; This is not really as slow as it sounds.
  899. ;
  900. wdiskct6:                         ; write D6 to diskctl
  901.        bsr     rwdelay                ;       delay
  902.        move.w  D6,diskctl            ;       write it
  903.        bra     rwdelay                ;       delay and return
  904.  
  905. wdiskctl:                         ; write D7 to diskctl
  906.        bsr     rwdelay                ;       delay
  907.        move.w  D7,diskctl            ;       write it
  908.        bra     rwdelay                ;       delay and return
  909.  
  910. rdiskct7:                         ; read diskctl into D7
  911.        bsr     rwdelay                ;       delay
  912.        move.w  diskctl,D7            ;       read it
  913.        bra     rwdelay                ;       delay and return
  914.  
  915. rdiskctl:                         ; read diskctl into D0
  916.        bsr     rwdelay                ;       delay
  917.        move.w  diskctl,D0            ;       read it
  918. ; And here's the delay loop:
  919. rwdelay:
  920.        move     SR,-(A7)             ; save flags
  921.        move.w  D7,-(A7)             ; save counter register
  922.        move.w  #0x20,D7             ; 0x20 seems about right...
  923. rwdly1: dbf     D7,rwdly1            ; busy-loop: give 1770 time to settle
  924.        move.w  (A7)+,D7             ; restore register, flags, and return
  925.        move     (A7)+,SR
  926.        rts
  927.  
  928. ;-------------------------------------
  929. regsave:    dc.l     1      ; PC relative data area
  930.         dc.l     2
  931.         dc.l     3
  932.         dc.l     4
  933.         dc.l     5
  934.         dc.l     6
  935.         dc.l     7
  936.         dc.l     8
  937.         dc.l     9
  938.  
  939.  
  940. }        /* MY GOD!  It's DONE!  */
  941.  
  942.