Home | History | Annotate | Line # | Download | only in obio
iwm.s revision 1.2.22.1
      1  1.2.22.1  thorpej /*	$NetBSD: iwm.s,v 1.2.22.1 2002/01/10 19:45:45 thorpej Exp $	*/
      2       1.1   scottr 
      3       1.1   scottr /*
      4       1.2   scottr  * Copyright (c) 1996-99 Hauke Fath.  All rights reserved.
      5       1.1   scottr  *
      6       1.1   scottr  * Redistribution and use in source and binary forms, with or without
      7       1.1   scottr  * modification, are permitted provided that the following conditions
      8       1.1   scottr  * are met:
      9       1.1   scottr  * 1. Redistributions of source code must retain the above copyright
     10       1.1   scottr  *    notice, this list of conditions and the following disclaimer.
     11       1.1   scottr  * 2. Redistributions in binary form must reproduce the above copyright
     12       1.1   scottr  *    notice, this list of conditions and the following disclaimer in the
     13       1.1   scottr  *    documentation and/or other materials provided with the distribution.
     14       1.1   scottr  * 3. The name of the author may not be used to endorse or promote products
     15       1.1   scottr  *    derived from this software without specific prior written permission.
     16       1.1   scottr  *
     17       1.1   scottr  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18       1.1   scottr  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19       1.1   scottr  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20       1.1   scottr  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21       1.1   scottr  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22       1.1   scottr  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23       1.1   scottr  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24       1.1   scottr  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25       1.1   scottr  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26       1.1   scottr  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27       1.1   scottr  */
     28       1.1   scottr 
     29       1.1   scottr /*
     30       1.1   scottr  * iwm.s -- low level routines for Sony floppy disk access.
     31       1.1   scottr  * The present implementation supports the 800K GCR format on non-DMA
     32       1.1   scottr  * machines.
     33       1.1   scottr  *
     34       1.1   scottr  * The IWM and SWIM chips run in polled mode; they are not capable of
     35       1.1   scottr  * interrupting the CPU. That's why interrupts need only be blocked
     36       1.1   scottr  * when there is simply no time for interrupt routine processing,
     37       1.1   scottr  * i.e. during data transfers.
     38       1.1   scottr  *
     39       1.1   scottr  * o  The local routines do not block any interrupts.
     40       1.1   scottr  *
     41       1.1   scottr  * o  The iwmXXX() routines that set/get IWM or drive settings are not
     42       1.1   scottr  *    time critical and do not block interrupts.
     43       1.1   scottr  *
     44       1.1   scottr  * o  The iwmXXX() routines that are called to perform data transfers
     45       1.1   scottr  *    block all interrupts because otherwise the current sector data
     46       1.1   scottr  *    would be lost.
     47       1.1   scottr  *    The old status register content is stored on the stack.
     48       1.1   scottr  *
     49       1.2   scottr  * o  We run at spl4 to give the NMI switch a chance. All currently
     50       1.2   scottr  *    supported machines have no interrupt sources > 4 (SSC) -- the
     51       1.2   scottr  *    Q700 interrupt levels can be shifted around in A/UX mode,
     52       1.2   scottr  *    but we're not there, yet.
     53       1.2   scottr  *
     54       1.1   scottr  * o  As a special case iwmReadSectHdr() must run with interrupts disabled
     55       1.1   scottr  *    (it transfers data). Depending on the needs of the caller, it
     56       1.1   scottr  *    may be necessary to block interrupts after completion of the routine
     57       1.1   scottr  *    so interrupt handling is left to the caller.
     58       1.1   scottr  *
     59       1.1   scottr  * If we wanted to deal with incoming serial data / serial interrupts,
     60       1.1   scottr  * we would have to either call zshard(0) {mac68k/dev/zs.c} or
     61       1.1   scottr  * zsc_intr_hard(0) {sys/dev/ic/z8530sc.c}. Or we would have to roll our
     62       1.1   scottr  * own as both of the listed function calls look rather expensive compared
     63       1.1   scottr  * to a 'tst.b REGADDR ; bne NN'.
     64       1.1   scottr  */
     65       1.1   scottr 
     66       1.1   scottr #include <m68k/asm.h>
     67       1.1   scottr 
     68       1.2   scottr #include <mac68k/obio/iwmreg.h>
     69       1.1   scottr 
     70       1.1   scottr #define USE_DELAY	0	/* "1" bombs for unknown reasons */
     71       1.1   scottr 
     72       1.1   scottr 
     73       1.1   scottr /*
     74       1.1   scottr  * References to global name space
     75       1.1   scottr  */
     76  1.2.22.1  thorpej 	.extern	_C_LABEL(TimeDBRA)	| in mac68k/macrom.c
     77  1.2.22.1  thorpej 	.extern _C_LABEL(Via1Base)	| in mac68k/machdep.c
     78  1.2.22.1  thorpej 	.extern	_C_LABEL(IWMBase)	| in iwm_fd.c
     79       1.1   scottr 
     80       1.1   scottr 
     81       1.1   scottr 	.data
     82       1.1   scottr 
     83       1.1   scottr diskTo:
     84       1.1   scottr 	/*
     85       1.1   scottr 	 * Translation table from 'disk bytes' to 6 bit 'nibbles',
     86       1.1   scottr 	 * taken from the .Sony driver.
     87       1.1   scottr 	 * This could be made a loadable table (via ioctls) to read
     88       1.1   scottr 	 * e.g. ProDOS disks (there is a hook for such a table in .Sony).
     89       1.1   scottr 	 */
     90       1.1   scottr 	.byte	/* 90 */  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01
     91       1.1   scottr 	.byte	/* 98 */  0xFF, 0xFF, 0x02, 0x03, 0xFF, 0x04, 0x05, 0x06
     92       1.1   scottr 	.byte	/* A0 */  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x08
     93       1.1   scottr 	.byte	/* A8 */  0xFF, 0xFF, 0xFF, 0x09, 0x0A, 0x0B, 0x0C, 0x0D
     94       1.1   scottr 	.byte	/* B0 */  0xFF, 0xFF, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13
     95       1.1   scottr 	.byte	/* B8 */  0xFF, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A
     96       1.1   scottr 	.byte	/* C0 */  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
     97       1.1   scottr 	.byte	/* C8 */  0xFF, 0xFF, 0xFF, 0x1B, 0xFF, 0x1C, 0x1D, 0x1E
     98       1.1   scottr 	.byte	/* D0 */  0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0x20, 0x21
     99       1.1   scottr 	.byte	/* D8 */  0xFF, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28
    100       1.1   scottr 	.byte	/* E0 */  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x29, 0x2A, 0x2B
    101       1.1   scottr 	.byte	/* E8 */  0xFF, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32
    102       1.1   scottr 	.byte	/* F0 */  0xFF, 0xFF, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38
    103       1.1   scottr 	.byte	/* F8 */  0xFF, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F
    104       1.1   scottr 
    105       1.1   scottr hdrLeadIn:
    106       1.1   scottr 	.byte	0xD5, 0xAA, 0x96
    107       1.1   scottr 
    108       1.1   scottr hdrLeadOut:
    109       1.1   scottr 	.byte	0xDE, 0xAA, 0xFF
    110       1.1   scottr 
    111       1.1   scottr dataLeadIn:
    112       1.1   scottr 	.byte	0xD5, 0xAA, 0xAD
    113       1.1   scottr 
    114       1.1   scottr dataLeadOut:
    115       1.1   scottr 	.byte	0xDE, 0xAA, 0xFF, 0xFF
    116       1.1   scottr 
    117       1.1   scottr 
    118       1.1   scottr toDisk:
    119       1.1   scottr 	/*
    120       1.1   scottr 	 * Translation table from 6-bit nibbles [0x00..0x3f] to 'disk bytes'
    121       1.1   scottr 	 */
    122       1.1   scottr 	.byte	/* 00 */  0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6
    123       1.1   scottr 	.byte	/* 08 */  0xA7, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB2, 0xB3
    124       1.1   scottr 	.byte	/* 10 */  0xB4, 0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC
    125       1.1   scottr 	.byte	/* 18 */  0xBD, 0xBE, 0xBF, 0xCB, 0xCD, 0xCE, 0xCF, 0xD3
    126       1.1   scottr 	.byte	/* 20 */  0xD6, 0xD7, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE
    127       1.1   scottr 	.byte	/* 28 */  0xDF, 0xE5, 0xE6, 0xE7, 0xE9, 0xEA, 0xEB, 0xEC
    128       1.1   scottr 	.byte	/* 30 */  0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xf5, 0xF6
    129       1.1   scottr 	.byte	/* 38 */  0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
    130       1.1   scottr 
    131       1.1   scottr syncPattern:
    132       1.1   scottr 	/*
    133       1.1   scottr 	 * This sync pattern creates 4 sync chars with 10 bits each that look
    134       1.1   scottr 	 * like 0011111111b (i.e. 0x0FF). As the IWM ignores leading zero
    135       1.1   scottr 	 * bits, it locks on 0xFF after the third sync byte.
    136       1.1   scottr 	 * For convenience, the bytes of the sector data lead-in
    137       1.1   scottr 	 * (D5 AA AD) follow.
    138       1.1   scottr 	 */
    139       1.1   scottr 	.byte	0xFF, 0x3F, 0xCF, 0xF3, 0xFC, 0xFF
    140       1.1   scottr 	.byte	0xD5, 0xAA, 0xAD
    141       1.1   scottr 
    142       1.1   scottr 
    143       1.1   scottr 
    144       1.1   scottr 	.text
    145       1.1   scottr 
    146       1.1   scottr /*
    147       1.1   scottr  * Register conventions:
    148  1.2.22.1  thorpej  *	%a0	IWM base address
    149  1.2.22.1  thorpej  *	%a1	VIA1 base address
    150       1.1   scottr  *
    151  1.2.22.1  thorpej  *	%d0	return value (0 == no error)
    152       1.1   scottr  *
    153       1.1   scottr  * Upper bits in data registers that are not cleared give nasty
    154       1.1   scottr  * (pseudo-) random errors when building an address. Make sure those
    155       1.1   scottr  *  registers are cleaned with a moveq before use!
    156       1.1   scottr  */
    157       1.1   scottr 
    158       1.1   scottr 
    159       1.1   scottr 
    160       1.1   scottr /**
    161       1.1   scottr  **	Export wrappers
    162       1.1   scottr  **/
    163       1.1   scottr 
    164       1.1   scottr /*
    165       1.1   scottr  * iwmQueryDrvFlags -- export wrapper for driveStat
    166       1.1   scottr  *
    167       1.1   scottr  * Parameters:	stack	l	drive selector
    168       1.1   scottr  *		stack	l	register selector
    169  1.2.22.1  thorpej  * Returns:	%d0		flag
    170       1.1   scottr  */
    171       1.1   scottr ENTRY(iwmQueryDrvFlag)
    172  1.2.22.1  thorpej 	link	%a6,#0
    173  1.2.22.1  thorpej 	moveml	%d1/%a0-%a1,%sp@-
    174  1.2.22.1  thorpej 	movel	_C_LABEL(IWMBase),%a0
    175  1.2.22.1  thorpej 	movel	_C_LABEL(Via1Base),%a1
    176       1.1   scottr 
    177  1.2.22.1  thorpej 	movel	%a6@(8),%d0		| Get drive #
    178       1.1   scottr 	beq	quDrv00
    179  1.2.22.1  thorpej 	cmpl	#1,%d0
    180       1.1   scottr 	beq	quDrv01
    181       1.1   scottr 
    182       1.1   scottr 	bra	quDone			| Invalid drive #
    183       1.1   scottr 
    184       1.1   scottr quDrv00:
    185  1.2.22.1  thorpej 	tstb	%a0@(intDrive)		| SELECT; choose drive #0
    186       1.1   scottr 	bra	queryDrv
    187       1.1   scottr 
    188       1.1   scottr quDrv01:
    189  1.2.22.1  thorpej 	tstb	%a0@(extDrive)		| SELECT; choose drive #1
    190       1.1   scottr 
    191       1.1   scottr queryDrv:
    192  1.2.22.1  thorpej 	movel	%a6@(12),%d0		| Get register #
    193       1.1   scottr 	bsr	driveStat
    194       1.1   scottr 
    195       1.1   scottr quDone:
    196  1.2.22.1  thorpej 	moveml	%sp@+,%d1/%a0-%a1
    197  1.2.22.1  thorpej 	unlk	%a6
    198       1.1   scottr 	rts
    199       1.1   scottr 
    200       1.1   scottr 
    201       1.1   scottr /*
    202       1.1   scottr  * iwmReadSectHdr -- read and decode the next available sector header.
    203       1.1   scottr  *
    204       1.1   scottr  * Parameters:	stack	l	Address of sector header struct (I/O)
    205       1.1   scottr  *				b	side (0, 1)
    206       1.1   scottr  *				b	track (0..79)
    207       1.1   scottr  *				b	sector (0..11)
    208  1.2.22.1  thorpej  * Returns:	%d0		result code
    209       1.1   scottr  */
    210       1.1   scottr ENTRY(iwmReadSectHdr)
    211  1.2.22.1  thorpej 	link	%a6,#0
    212  1.2.22.1  thorpej 	moveml	%d1-%d5/%a0-%a4,%sp@-
    213  1.2.22.1  thorpej 	movel	%a6@(0x08),%a4		| Get param block address
    214       1.1   scottr 	bsr	readSectHdr
    215  1.2.22.1  thorpej 	moveml	%sp@+,%d1-%d5/%a0-%a4
    216  1.2.22.1  thorpej 	unlk	%a6
    217       1.1   scottr 	rts
    218       1.1   scottr 
    219       1.1   scottr 
    220       1.1   scottr 
    221       1.1   scottr /**
    222       1.1   scottr  **	Exported functions
    223       1.1   scottr  **/
    224       1.1   scottr 
    225       1.1   scottr /*
    226       1.1   scottr  * iwmInit -- Initialize IWM chip.
    227       1.1   scottr  *
    228       1.1   scottr  * Parameters:	-
    229  1.2.22.1  thorpej  * Returns:	%d0		result code
    230       1.1   scottr  */
    231       1.1   scottr ENTRY(iwmInit)
    232  1.2.22.1  thorpej 	link	%a6,#0
    233  1.2.22.1  thorpej 	moveml	%d2/%a0,%sp@-
    234  1.2.22.1  thorpej 	movel	_C_LABEL(IWMBase),%a0
    235       1.1   scottr 
    236       1.1   scottr 	/*
    237       1.1   scottr 	 * Reset IWM to known state (clear disk I/O latches)
    238       1.1   scottr 	 */
    239  1.2.22.1  thorpej 	tstb	%a0@(ph0L)		| CA0
    240  1.2.22.1  thorpej 	tstb	%a0@(ph1L)		| CA1
    241  1.2.22.1  thorpej 	tstb	%a0@(ph2L)		| CA2
    242  1.2.22.1  thorpej 	tstb	%a0@(ph3L)		| LSTRB
    243  1.2.22.1  thorpej 
    244  1.2.22.1  thorpej 	tstb	%a0@(mtrOff)		| ENABLE; make sure drive is off
    245  1.2.22.1  thorpej 	tstb	%a0@(intDrive)		| SELECT; choose drive 1
    246  1.2.22.1  thorpej 	moveq	#0x1F,%d0		| XXX was 0x17 -- WHY!?
    247       1.1   scottr 
    248       1.1   scottr 	/*
    249       1.1   scottr 	 * First do it quick...
    250       1.1   scottr 	 */
    251  1.2.22.1  thorpej 	tstb	%a0@(q6H)
    252  1.2.22.1  thorpej 	andb	%a0@(q7L),%d0		| status register
    253  1.2.22.1  thorpej 	tstb	%a0@(q6L)
    254  1.2.22.1  thorpej 	cmpib	#iwmMode,%d0		| all is well??
    255       1.1   scottr 	beq	initDone
    256       1.1   scottr 
    257       1.1   scottr 	/*
    258       1.1   scottr 	 * If this doesn't succeed (e.g. drive still running),
    259       1.1   scottr 	 * we do it thoroughly.
    260       1.1   scottr 	 */
    261  1.2.22.1  thorpej 	movel	#0x00080000,%d2		| ca. 500,000 retries = 1.5 sec
    262       1.1   scottr initLp:
    263  1.2.22.1  thorpej 	moveq	#initIWMErr,%d0		| Initialization error
    264  1.2.22.1  thorpej 	subql	#1,%d2
    265       1.1   scottr 	bmi	initErr
    266  1.2.22.1  thorpej 	tstb	%a0@(mtrOff)		| disable drive
    267  1.2.22.1  thorpej 	tstb	%a0@(q6H)
    268  1.2.22.1  thorpej 	moveq	#0x3F,%d0
    269  1.2.22.1  thorpej 	andb	%a0@(q7L),%d0
    270  1.2.22.1  thorpej 	bclr	#5,%d0			| Reset bit 5 and set Z flag
    271       1.1   scottr 					| according to previous state
    272       1.1   scottr 	bne	initLp			| Loop if drive still on
    273  1.2.22.1  thorpej 	cmpib	#iwmMode,%d0
    274       1.1   scottr 	beq	initDone
    275  1.2.22.1  thorpej 	moveb	#iwmMode,%a0@(q7H)	| Init IWM
    276  1.2.22.1  thorpej 	tstb	%a0@(q7L)
    277       1.1   scottr 	bra	initLp
    278       1.1   scottr 
    279       1.1   scottr initDone:
    280  1.2.22.1  thorpej 	tstb	%a0@(q6L)		| Prepare IWM for data
    281  1.2.22.1  thorpej 	moveq	#0,%d0			| noErr
    282       1.1   scottr 
    283       1.1   scottr initErr:
    284  1.2.22.1  thorpej 	moveml	%sp@+,%d2/%a0
    285  1.2.22.1  thorpej 	unlk	%a6
    286       1.1   scottr 	rts
    287       1.1   scottr 
    288       1.1   scottr 
    289       1.1   scottr /*
    290       1.1   scottr  * iwmCheckDrive -- Check if given drive is available and return bit vector
    291       1.1   scottr  *	with capabilities (SS/DS, disk inserted, ...)
    292       1.1   scottr  *
    293       1.1   scottr  * Parameters:	stack	l	Drive number (0,1)
    294  1.2.22.1  thorpej  * Returns:	%d0	Bit	 0 - 0 = Drive is single sided
    295       1.1   scottr  *				 1 - 0 = Disk inserted
    296       1.1   scottr  *				 2 - 0 = Motor is running
    297       1.1   scottr  *				 3 - 0 = Disk is write protected
    298       1.1   scottr  *				 4 - 0 = Disk is DD
    299       1.1   scottr  *				31 - (-1) No drive / invalid drive #
    300       1.1   scottr  */
    301       1.1   scottr ENTRY(iwmCheckDrive)
    302  1.2.22.1  thorpej 	link	%a6,#0
    303  1.2.22.1  thorpej 	moveml	%d1/%a0-%a1,%sp@-
    304  1.2.22.1  thorpej 	movel	_C_LABEL(IWMBase),%a0
    305  1.2.22.1  thorpej 	movel	_C_LABEL(Via1Base),%a1
    306       1.1   scottr 
    307  1.2.22.1  thorpej 	moveq	#-1,%d1			| no drive
    308       1.1   scottr 
    309  1.2.22.1  thorpej 	movel	%a6@(0x08),%d0		| check drive #
    310       1.1   scottr 	beq	chkDrv00
    311  1.2.22.1  thorpej 	cmpl	#1,%d0
    312       1.1   scottr 	beq	chkDrv01
    313       1.1   scottr 
    314       1.1   scottr 	bra	chkDone			| invalid drive #
    315       1.1   scottr 
    316       1.1   scottr chkDrv00:
    317  1.2.22.1  thorpej 	tstb	%a0@(intDrive)		| SELECT; choose drive #0
    318       1.1   scottr 	bra	chkDrive
    319       1.1   scottr 
    320       1.1   scottr chkDrv01:
    321  1.2.22.1  thorpej 	tstb	%a0@(extDrive)		| SELECT; choose drive #1
    322       1.1   scottr 
    323       1.1   scottr chkDrive:
    324  1.2.22.1  thorpej 	moveq	#-2,%d1			| error code
    325  1.2.22.1  thorpej 	moveq	#drvInstalled,%d0	| Drive installed?
    326       1.1   scottr 	bsr	driveStat
    327       1.1   scottr 	bmi	chkDone			| no drive
    328       1.1   scottr 
    329  1.2.22.1  thorpej 	moveq	#0,%d1			| Drive found
    330  1.2.22.1  thorpej 	tstb	%a0@(mtrOn)		| ENABLE; activate drive
    331  1.2.22.1  thorpej 	moveq	#singleSided,%d0	| Drive is single-sided?
    332       1.1   scottr 	bsr	driveStat
    333       1.1   scottr 	bpl	chkHasDisk
    334       1.1   scottr 	/*
    335       1.1   scottr 	 * Drive is double-sided -- this is not really a surprise as the
    336       1.1   scottr 	 * old ss 400k drive needs disk speed control from the Macintosh
    337       1.1   scottr 	 * and we're not doing that here. Anyway - just in case...
    338       1.1   scottr 	 * I am not sure m680x0 Macintoshes (x>0) support 400K drives at all
    339       1.1   scottr 	 * due to their radically different sound support.
    340       1.1   scottr 	 */
    341  1.2.22.1  thorpej 	bset	#0,%d1			| 1 = no.
    342       1.1   scottr chkHasDisk:
    343  1.2.22.1  thorpej 	moveq	#diskInserted,%d0	| Disk inserted?
    344       1.1   scottr 	bsr	driveStat
    345       1.1   scottr 	bpl	chkMotorOn
    346  1.2.22.1  thorpej 	bset	#1,%d1			| 1 = No.
    347       1.1   scottr 	bra	chkDone
    348       1.1   scottr chkMotorOn:
    349  1.2.22.1  thorpej 	moveq	#drvMotorState,%d0	| Motor is running?
    350       1.1   scottr 	bsr	driveStat
    351       1.1   scottr 	bpl	chkWrtProt
    352  1.2.22.1  thorpej 	bset	#2,%d1			| 1 = No.
    353       1.1   scottr chkWrtProt:
    354  1.2.22.1  thorpej 	moveq	#writeProtected,%d0	| Disk is write protected?
    355       1.1   scottr 	bsr	driveStat
    356       1.1   scottr 	bpl	chkDD_HD
    357  1.2.22.1  thorpej 	bset	#3,%d1			| 1 = No.
    358       1.1   scottr chkDD_HD:
    359  1.2.22.1  thorpej 	moveq	#diskIsHD,%d0		| Disk is HD? (was "drive installed")
    360       1.1   scottr 	bsr	driveStat
    361       1.1   scottr 	bpl	chkDone
    362  1.2.22.1  thorpej 	bset	#4,%d1			| 1 = No.
    363       1.1   scottr chkDone:
    364  1.2.22.1  thorpej 	movel	%d1,%d0
    365  1.2.22.1  thorpej 	moveml	%sp@+,%d1/%a0-%a1
    366  1.2.22.1  thorpej 	unlk	%a6
    367       1.1   scottr 	rts
    368       1.1   scottr 
    369       1.1   scottr 
    370       1.1   scottr /*
    371       1.1   scottr  * iwmDiskEject -- post EJECT command and toggle LSTRB line to give a
    372       1.1   scottr  * strobe signal.
    373       1.1   scottr  * IM III says pulse length = 500 ms, but we seem to get away with
    374       1.1   scottr  * less delay; after all, we spin lock the CPU with it.
    375       1.1   scottr  *
    376       1.1   scottr  * Parameters:	stack	l	drive number (0,1)
    377  1.2.22.1  thorpej  *		%a0		IWMBase
    378  1.2.22.1  thorpej  *		%a1		VIABase
    379  1.2.22.1  thorpej  * Returns:	%d0		result code
    380       1.1   scottr  */
    381       1.1   scottr ENTRY(iwmDiskEject)
    382  1.2.22.1  thorpej 	link	%a6,#0
    383  1.2.22.1  thorpej 	movel	_C_LABEL(IWMBase),%a0
    384  1.2.22.1  thorpej 	movel	_C_LABEL(Via1Base),%a1
    385       1.1   scottr 
    386  1.2.22.1  thorpej 	movel	%a6@(0x08),%d0		| Get drive #
    387       1.1   scottr 	beq	ejDrv00
    388  1.2.22.1  thorpej 	cmpw	#1,%d0
    389       1.1   scottr 	beq	ejDrv01
    390       1.1   scottr 
    391       1.1   scottr 	bra	ejDone			| Invalid drive #
    392       1.1   scottr 
    393       1.1   scottr ejDrv00:
    394  1.2.22.1  thorpej 	tstb	%a0@(intDrive)		| SELECT; choose drive #0
    395       1.1   scottr 	bra	ejDisk
    396       1.1   scottr 
    397       1.1   scottr ejDrv01:
    398  1.2.22.1  thorpej 	tstb	%a0@(extDrive)		| SELECT; choose drive #1
    399       1.1   scottr ejDisk:
    400  1.2.22.1  thorpej 	tstb	%a0@(mtrOn)		| ENABLE; activate drive
    401       1.1   scottr 
    402  1.2.22.1  thorpej 	moveq	#motorOffCmd,%d0	| Motor off
    403       1.1   scottr  	bsr	driveCmd
    404       1.1   scottr 
    405  1.2.22.1  thorpej 	moveq	#diskInserted,%d0	| Disk inserted?
    406       1.1   scottr 	bsr	driveStat
    407       1.1   scottr 	bmi	ejDone
    408       1.1   scottr 
    409  1.2.22.1  thorpej 	moveq	#ejectDiskCmd,%d0	| Eject it
    410       1.1   scottr 	bsr	selDriveReg
    411       1.1   scottr 
    412  1.2.22.1  thorpej 	tstb	%a0@(ph3H)		| LSTRB high
    413       1.1   scottr #if USE_DELAY
    414  1.2.22.1  thorpej 	movel	#1000,%sp@-		| delay 1 ms
    415       1.1   scottr 	jsr	_C_LABEL(delay)
    416  1.2.22.1  thorpej 	addqw	#4,%sp			| clean up stack
    417       1.1   scottr #else
    418  1.2.22.1  thorpej 	movew	#1,%d0
    419       1.1   scottr 	bsr	iwmDelay
    420       1.1   scottr #endif
    421  1.2.22.1  thorpej 	tstb	%a0@(ph3L)		| LSTRB low
    422  1.2.22.1  thorpej 	moveq	#0,%d0			| All's well...
    423       1.1   scottr ejDone:
    424  1.2.22.1  thorpej 	unlk	%a6
    425       1.1   scottr 	rts
    426       1.1   scottr 
    427       1.1   scottr 
    428       1.1   scottr /*
    429       1.1   scottr  * iwmSelectDrive -- select internal (0) / external (1) drive.
    430       1.1   scottr  *
    431       1.1   scottr  * Parameters:	stack	l	drive ID (0/1)
    432  1.2.22.1  thorpej  * Returns:	%d0		drive #
    433       1.1   scottr  */
    434       1.1   scottr ENTRY(iwmSelectDrive)
    435  1.2.22.1  thorpej 	link	%a6,#0
    436  1.2.22.1  thorpej 	moveml	%a0-%a1,%sp@-
    437  1.2.22.1  thorpej 	movel	_C_LABEL(IWMBase),%a0
    438  1.2.22.1  thorpej 	movel	_C_LABEL(Via1Base),%a1
    439       1.1   scottr 
    440  1.2.22.1  thorpej 	movel	%a6@(8),%d0		| Get drive #
    441       1.1   scottr 	bne	extDrv
    442  1.2.22.1  thorpej 	tstb	%a0@(intDrive)
    443       1.1   scottr 	bra	sdDone
    444       1.1   scottr extDrv:
    445  1.2.22.1  thorpej 	tstb	%a0@(extDrive)
    446       1.1   scottr sdDone:
    447  1.2.22.1  thorpej 	moveml	%sp@+,%a0-%a1
    448  1.2.22.1  thorpej 	unlk	%a6
    449       1.1   scottr 	rts
    450       1.1   scottr 
    451       1.1   scottr 
    452       1.1   scottr /*
    453       1.1   scottr  * iwmMotor -- switch drive motor on/off
    454       1.1   scottr  *
    455       1.1   scottr  * Parameters:	stack	l	drive ID (0/1)
    456       1.1   scottr  *		stack	l	on(1)/off(0)
    457  1.2.22.1  thorpej  * Returns:	%d0		motor cmd
    458       1.1   scottr  */
    459       1.1   scottr ENTRY(iwmMotor)
    460  1.2.22.1  thorpej 	link	%a6,#0
    461  1.2.22.1  thorpej 	moveml	%a0-%a1,%sp@-
    462  1.2.22.1  thorpej 	movel	_C_LABEL(IWMBase),%a0
    463  1.2.22.1  thorpej 	movel	_C_LABEL(Via1Base),%a1
    464       1.1   scottr 
    465  1.2.22.1  thorpej 	movel	%a6@(8),%d0		| Get drive #
    466       1.1   scottr 	bne	mtDrv1
    467  1.2.22.1  thorpej 	tstb	%a0@(intDrive)
    468       1.1   scottr 	bra	mtSwitch
    469       1.1   scottr mtDrv1:
    470  1.2.22.1  thorpej 	tstb	%a0@(extDrive)
    471       1.1   scottr mtSwitch:
    472  1.2.22.1  thorpej 	movel	#motorOnCmd,%d0		| Motor ON
    473  1.2.22.1  thorpej 	tstl	%a6@(12)
    474       1.1   scottr 	bne	mtON
    475  1.2.22.1  thorpej 	movel	#motorOffCmd,%d0
    476       1.1   scottr mtON:
    477       1.1   scottr 	bsr	driveCmd
    478       1.1   scottr 
    479  1.2.22.1  thorpej 	moveml	%sp@+,%a0-%a1
    480  1.2.22.1  thorpej 	unlk	%a6
    481       1.1   scottr 	rts
    482       1.1   scottr 
    483       1.1   scottr 
    484       1.1   scottr /*
    485       1.1   scottr  * iwmSelectSide -- select side 0 (lower head) / side 1 (upper head).
    486       1.1   scottr  *
    487       1.1   scottr  * This MUST be called immediately before an actual read/write access.
    488       1.1   scottr  *
    489       1.1   scottr  * Parameters:	stack	l	side bit (0/1)
    490       1.1   scottr  * Returns:	-
    491       1.1   scottr  */
    492       1.1   scottr ENTRY(iwmSelectSide)
    493  1.2.22.1  thorpej 	link	%a6,#0
    494  1.2.22.1  thorpej 	moveml	%d1/%a0-%a1,%sp@-
    495  1.2.22.1  thorpej 	movel	_C_LABEL(IWMBase),%a0
    496  1.2.22.1  thorpej 	movel	_C_LABEL(Via1Base),%a1
    497       1.1   scottr 
    498  1.2.22.1  thorpej 	moveq	#0x0B,%d0		| Drive ready for reading?
    499       1.1   scottr 	bsr	selDriveReg		| (undocumented)
    500       1.1   scottr ss01:
    501       1.1   scottr 	bsr	dstatus
    502       1.1   scottr 	bmi	ss01
    503       1.1   scottr 
    504  1.2.22.1  thorpej 	moveq	#rdDataFrom0,%d0	| Lower head
    505  1.2.22.1  thorpej 	movel	%a6@(0x08),%d1		| Get side #
    506       1.1   scottr 	beq	ssSide0
    507  1.2.22.1  thorpej 	moveq	#rdDataFrom1,%d0	| Upper head
    508       1.1   scottr ssSide0:
    509       1.1   scottr 	bsr	driveStat
    510       1.1   scottr 
    511  1.2.22.1  thorpej 	moveml	%sp@+,%d1/%a0-%a1
    512  1.2.22.1  thorpej 	unlk	%a6
    513       1.1   scottr 	rts
    514       1.1   scottr 
    515       1.1   scottr 
    516       1.1   scottr /*
    517       1.1   scottr  * iwmTrack00 -- move head to track 00 for drive calibration.
    518       1.1   scottr  *
    519       1.1   scottr  * XXX Drive makes funny noises during resore. Tune delay/retry count?
    520       1.1   scottr  *
    521       1.1   scottr  * Parameters:	-
    522  1.2.22.1  thorpej  * Returns:	%d0		result code
    523       1.1   scottr  */
    524       1.1   scottr ENTRY(iwmTrack00)
    525  1.2.22.1  thorpej 	link	%a6,#0
    526  1.2.22.1  thorpej 	moveml	%d1-%d4/%a0-%a1,%sp@-
    527  1.2.22.1  thorpej 	movel	_C_LABEL(IWMBase),%a0
    528  1.2.22.1  thorpej 	movel	_C_LABEL(Via1Base),%a1
    529       1.1   scottr 
    530  1.2.22.1  thorpej 	moveq	#motorOnCmd,%d0		| Switch drive motor on
    531       1.1   scottr 	bsr	driveCmd
    532       1.1   scottr 
    533  1.2.22.1  thorpej 	moveq	#stepOutCmd,%d0		| Step out
    534       1.1   scottr 	bsr	driveCmd
    535       1.1   scottr 
    536  1.2.22.1  thorpej 	movew	#100,%d2		| Max. tries
    537       1.1   scottr t0Retry:
    538  1.2.22.1  thorpej 	moveq	#atTrack00,%d0		| Already at track 0?
    539       1.1   scottr 	bsr	driveStat
    540       1.1   scottr 	bpl	isTrack00		| Track 0 => Bit 7 = 0
    541       1.1   scottr 
    542  1.2.22.1  thorpej 	moveq	#doStepCmd,%d0		| otherwise step
    543       1.1   scottr 	bsr	driveCmd
    544  1.2.22.1  thorpej 	movew	#80,%d4			| Retries
    545       1.1   scottr t0Still:
    546  1.2.22.1  thorpej 	moveq	#stillStepping,%d0	| Drive is still stepping?
    547       1.1   scottr 	bsr	driveStat
    548  1.2.22.1  thorpej 	dbmi	%d4,t0Still
    549       1.1   scottr 
    550  1.2.22.1  thorpej 	cmpiw	#-1,%d4
    551       1.1   scottr 	bne	t002
    552       1.1   scottr 
    553  1.2.22.1  thorpej 	moveq	#cantStepErr,%d0	| Not ready after many retries
    554       1.1   scottr 	bra	t0Done
    555       1.1   scottr t002:
    556       1.1   scottr 
    557       1.1   scottr #if USE_DELAY
    558  1.2.22.1  thorpej 	movel	#15000,%sp@-
    559       1.1   scottr 	jsr	_C_LABEL(delay)		| in mac68k/clock.c
    560  1.2.22.1  thorpej 	addqw	#4,%sp
    561       1.1   scottr #else
    562  1.2.22.1  thorpej 	movew	#15,%d0
    563       1.1   scottr 	bsr	iwmDelay
    564       1.1   scottr #endif
    565       1.1   scottr 
    566  1.2.22.1  thorpej 	dbra	%d2,t0Retry
    567       1.1   scottr 
    568  1.2.22.1  thorpej 	moveq	#tk0BadErr,%d0		| Can't find track 00!!
    569       1.1   scottr 	bra	t0Done
    570       1.1   scottr 
    571       1.1   scottr isTrack00:
    572  1.2.22.1  thorpej 	moveq	#0,%d0
    573       1.1   scottr t0Done:
    574  1.2.22.1  thorpej 	moveml	%sp@+,%d1-%d4/%a0-%a1
    575  1.2.22.1  thorpej 	unlk	%a6
    576  1.2.22.1  thorpej 	rts
    577       1.1   scottr 
    578       1.1   scottr 
    579       1.1   scottr /*
    580       1.1   scottr  * iwmSeek -- do specified # of steps (positive - in, negative - out).
    581       1.1   scottr  *
    582       1.1   scottr  * Parameters:	stack	l	# of steps
    583  1.2.22.1  thorpej  * returns:	%d0		result code
    584       1.1   scottr  */
    585       1.1   scottr ENTRY(iwmSeek)
    586  1.2.22.1  thorpej 	link	%a6,#0
    587  1.2.22.1  thorpej 	moveml	%d1-%d4/%a0-%a1,%sp@-
    588  1.2.22.1  thorpej 	movel	_C_LABEL(IWMBase),%a0
    589  1.2.22.1  thorpej 	movel	_C_LABEL(Via1Base),%a1
    590       1.1   scottr 
    591  1.2.22.1  thorpej 	moveq	#motorOnCmd,%d0		| Switch drive motor on
    592       1.1   scottr 	bsr	driveCmd
    593       1.1   scottr 
    594  1.2.22.1  thorpej 	moveq	#stepInCmd,%d0		| Set step IN
    595  1.2.22.1  thorpej 	movel	%a6@(8),%d2		| Get # of steps from stack
    596       1.1   scottr 	beq	stDone			| 0 steps? Nothing to do.
    597       1.1   scottr 	bpl	stepOut
    598       1.1   scottr 
    599  1.2.22.1  thorpej 	moveq	#stepOutCmd,%d0		| Set step OUT
    600  1.2.22.1  thorpej 	negl	%d2			| Make # of steps positive
    601       1.1   scottr stepOut:
    602  1.2.22.1  thorpej 	subql	#1,%d2			| Loop exits for -1
    603       1.1   scottr 	bsr	driveCmd		| Set direction
    604       1.1   scottr stLoop:
    605  1.2.22.1  thorpej 	moveq	#doStepCmd,%d0
    606       1.1   scottr 	bsr	driveCmd		| Step one!
    607  1.2.22.1  thorpej 	movew	#80,%d4			| Retries
    608       1.1   scottr st01:
    609  1.2.22.1  thorpej 	moveq	#stillStepping, %d0	| Drive is still stepping?
    610       1.1   scottr 	bsr	driveStat
    611  1.2.22.1  thorpej 	dbmi	%d4,st01
    612       1.1   scottr 
    613  1.2.22.1  thorpej 	cmpiw	#-1,%d4
    614       1.1   scottr 	bne	st02
    615       1.1   scottr 
    616  1.2.22.1  thorpej 	moveq	#cantStepErr,%d2	| Not ready after many retries
    617       1.1   scottr 	bra	stDone
    618       1.1   scottr st02:
    619       1.1   scottr 
    620       1.1   scottr #if USE_DELAY
    621  1.2.22.1  thorpej 	movel	#30,%sp@-
    622       1.1   scottr 	jsr	_C_LABEL(delay)		| in mac68k/clock.c
    623  1.2.22.1  thorpej 	addqw	#4,%sp
    624       1.1   scottr #else
    625  1.2.22.1  thorpej 	movew	_C_LABEL(TimeDBRA),%d4	| dbra loops per ms
    626  1.2.22.1  thorpej 	lsrw	#5,%d4			| DIV 32
    627  1.2.22.1  thorpej st03:	dbra	%d4,st03		| makes ca. 30 us
    628       1.1   scottr #endif
    629       1.1   scottr 
    630  1.2.22.1  thorpej 	dbra	%d2,stLoop
    631       1.1   scottr 
    632  1.2.22.1  thorpej 	moveq	#0,%d2			| All is well
    633       1.1   scottr stDone:
    634  1.2.22.1  thorpej 	movel	%d2,%d0
    635  1.2.22.1  thorpej 	moveml	%sp@+,%d1-%d4/%a0-%a1
    636  1.2.22.1  thorpej 	unlk	%a6
    637       1.1   scottr 	rts
    638       1.1   scottr 
    639       1.1   scottr 
    640       1.1   scottr /*
    641       1.1   scottr  * iwmReadSector -- read and decode the next available sector.
    642       1.1   scottr  *
    643       1.1   scottr  * TODO:	Poll SCC as long as interrupts are disabled (see top comment)
    644       1.1   scottr  *		Add a branch for Verify (compare to buffer)
    645       1.1   scottr  *		Understand and document the checksum algorithm!
    646       1.1   scottr  *
    647       1.2   scottr  *		XXX make "sizeof cylCache_t" a symbolic constant
    648       1.2   scottr  *
    649  1.2.22.1  thorpej  * Parameters:	%fp+08	l	Address of sector data buffer (512 bytes)
    650  1.2.22.1  thorpej  *		%fp+12	l	Address of sector header struct (I/O)
    651  1.2.22.1  thorpej  *		%fp+16	l	Address of cache buffer ptr array
    652  1.2.22.1  thorpej  * Returns:	%d0		result code
    653  1.2.22.1  thorpej  * Local:	%fp-2	w	CPU status register
    654  1.2.22.1  thorpej  *		%fp-3	b	side,
    655  1.2.22.1  thorpej  *		%fp-4	b	track,
    656  1.2.22.1  thorpej  *		%fp-5	b	sector wanted
    657  1.2.22.1  thorpej  *		%fp-6	b	retry count
    658  1.2.22.1  thorpej  *		%fp-7	b	sector read
    659       1.1   scottr  */
    660       1.1   scottr ENTRY(iwmReadSector)
    661  1.2.22.1  thorpej 	link	%a6,#-8
    662  1.2.22.1  thorpej 	moveml	%d1-%d7/%a0-%a5,%sp@-
    663       1.1   scottr 
    664  1.2.22.1  thorpej  	movel	_C_LABEL(Via1Base),%a1
    665  1.2.22.1  thorpej 	movel	%a6@(o_hdr),%a4		| Addr of sector header struct
    666       1.1   scottr 
    667  1.2.22.1  thorpej 	moveb	%a4@+,%a6@(-3)		| Save side bit,
    668  1.2.22.1  thorpej 	moveb	%a4@+,%a6@(-4)		| track#,
    669  1.2.22.1  thorpej 	moveb	%a4@,%a6@(-5)		| sector#
    670  1.2.22.1  thorpej 	moveb	#2*maxGCRSectors,%a6@(-6) | Max. retry count
    671       1.1   scottr 
    672  1.2.22.1  thorpej 	movew	%sr,%a6@(-2)		| Save CPU status register
    673  1.2.22.1  thorpej 	oriw	#0x0600,%sr		| Block all interrupts
    674       1.1   scottr 
    675       1.2   scottr rsNextSect:
    676  1.2.22.1  thorpej 	movel	%a6@(o_hdr),%a4		| Addr of sector header struct
    677       1.1   scottr 	bsr	readSectHdr		| Get next available SECTOR header
    678       1.1   scottr 	bne	rsDone			| Return if error
    679       1.1   scottr 
    680       1.1   scottr 	/*
    681       1.1   scottr 	 * Is this the right track & side? If not, return with error
    682       1.1   scottr 	 */
    683  1.2.22.1  thorpej 	movel	%a6@(o_hdr),%a4		| Sector header struct
    684       1.1   scottr 
    685  1.2.22.1  thorpej 	moveb	%a4@(o_side),%d1	| Get actual side
    686  1.2.22.1  thorpej 	lsrb	#3,%d1			| "Normalize" side bit (to bit 0)
    687  1.2.22.1  thorpej 	andb	#1,%d1
    688  1.2.22.1  thorpej 	moveb	%a6@(-3),%d2		| Get wanted side
    689  1.2.22.1  thorpej 	eorb	%d1,%d2			| Compare side bits
    690       1.1   scottr 	bne	rsSeekErr		| Should be equal!
    691       1.1   scottr 
    692  1.2.22.1  thorpej 	moveb	%a6@(-4),%d1		| Get track# we want
    693  1.2.22.1  thorpej 	cmpb	%a4@(o_track),%d1	| Compare to the header we've read
    694       1.1   scottr 	beq	rsGetSect
    695       1.2   scottr 
    696       1.1   scottr rsSeekErr:
    697  1.2.22.1  thorpej 	moveq	#seekErr,%d0		| Wrong track or side found
    698       1.1   scottr 	bra	rsDone
    699       1.1   scottr 
    700       1.1   scottr 	/*
    701       1.1   scottr 	 * Check for sector data lead-in 'D5 AA AD'
    702       1.1   scottr 	 * Registers:
    703  1.2.22.1  thorpej 	 *	%a0 points to data register of IWM as set up by readSectHdr
    704  1.2.22.1  thorpej 	 *	%a2 points to 'diskTo' translation table
    705  1.2.22.1  thorpej 	 *	%a4 points to tags buffer
    706       1.1   scottr 	 */
    707       1.1   scottr rsGetSect:
    708  1.2.22.1  thorpej 	moveb	%a4@(2),%a6@(-7)	| save sector number
    709  1.2.22.1  thorpej 	lea	%a4@(3),%a4		| Beginning of tag buffer
    710  1.2.22.1  thorpej 	moveq	#50,%d3			| Max. retries for sector lookup
    711       1.1   scottr rsLeadIn:
    712  1.2.22.1  thorpej 	lea	dataLeadIn,%a3		| Sector data lead-in
    713  1.2.22.1  thorpej 	moveq	#0x03,%d4		| is 3 bytes long
    714       1.1   scottr rsLI1:
    715  1.2.22.1  thorpej 	moveb	%a0@,%d2		| Get next byte
    716       1.1   scottr 	bpl	rsLI1
    717  1.2.22.1  thorpej 	dbra	%d3,rsLI2
    718  1.2.22.1  thorpej 	moveq	#noDtaMkErr,%d0		| Can't find a data mark
    719       1.1   scottr 	bra	rsDone
    720       1.1   scottr 
    721       1.1   scottr rsLI2:
    722  1.2.22.1  thorpej 	cmpb	%a3@+,%d2
    723       1.1   scottr 	bne	rsLeadIn		| If ne restart scan
    724  1.2.22.1  thorpej 	subqw	#1,%d4
    725       1.1   scottr 	bne	rsLI1
    726       1.2   scottr 
    727       1.1   scottr 	/*
    728       1.1   scottr 	 * We have found the lead-in. Now get the 12 tag bytes.
    729  1.2.22.1  thorpej 	 * (We leave %a3 pointing to 'dataLeadOut' for later.)
    730       1.1   scottr 	 */
    731       1.1   scottr rsTagNyb0:
    732  1.2.22.1  thorpej 	moveb	%a0@,%d3		| Get a char,
    733       1.1   scottr 	bpl	rsTagNyb0
    734  1.2.22.1  thorpej 	moveb	%a2@(0,%d3),%a4@+	| remap and store it
    735       1.1   scottr 
    736  1.2.22.1  thorpej 	moveq	#0,%d5			| Clear checksum registers
    737  1.2.22.1  thorpej 	moveq	#0,%d6
    738  1.2.22.1  thorpej 	moveq	#0,%d7
    739  1.2.22.1  thorpej 	moveq	#10,%d4			| Loop counter
    740  1.2.22.1  thorpej 	moveq	#0,%d3			| Data scratch reg
    741       1.1   scottr 
    742       1.1   scottr rsTags:
    743       1.1   scottr rsTagNyb1:
    744  1.2.22.1  thorpej 	moveb	%a0@,%d3		| Get 2 bit nibbles
    745       1.1   scottr 	bpl	rsTagNyb1
    746  1.2.22.1  thorpej 	moveb	%a2@(0,%d3),%d1		| Remap disk byte
    747  1.2.22.1  thorpej 	rolb	#2,%d1
    748  1.2.22.1  thorpej 	moveb	%d1,%d2
    749  1.2.22.1  thorpej 	andib	#0xC0,%d2		| Get top 2 bits for first byte
    750       1.1   scottr rsTagNyb2:
    751  1.2.22.1  thorpej 	moveb	%a0@,%d3		| Get first 6 bit nibble
    752       1.1   scottr 	bpl	rsTagNyb2
    753  1.2.22.1  thorpej 	orb	%a2@(0,%d3),%d2		| Remap it and complete first byte
    754       1.1   scottr 
    755  1.2.22.1  thorpej 	moveb	%d7,%d3			| The X flag bit (a copy of the carry
    756  1.2.22.1  thorpej 	addb	%d7,%d3			| flag) is added with the next addx
    757       1.1   scottr 
    758  1.2.22.1  thorpej 	rolb	#1,%d7
    759  1.2.22.1  thorpej 	eorb	%d7,%d2
    760  1.2.22.1  thorpej 	moveb	%d2,%a4@+		| Store tag byte
    761  1.2.22.1  thorpej 	addxb	%d2,%d5			| See above
    762  1.2.22.1  thorpej 
    763  1.2.22.1  thorpej 	rolb	#2,%d1
    764  1.2.22.1  thorpej 	moveb	%d1,%d2
    765  1.2.22.1  thorpej 	andib	#0xC0,%d2		| Get top 2 bits for second byte
    766       1.1   scottr rsTagNyb3:
    767  1.2.22.1  thorpej 	moveb	%a0@,%d3		| Get second 6 bit nibble
    768       1.1   scottr 	bpl	rsTagNyb3
    769  1.2.22.1  thorpej 	orb	%a2@(0,%d3),%d2		| remap it and complete byte
    770  1.2.22.1  thorpej 	eorb	%d5,%d2
    771  1.2.22.1  thorpej 	moveb	%d2,%a4@+		| Store tag byte
    772  1.2.22.1  thorpej 	addxb	%d2,%d6
    773       1.1   scottr 
    774  1.2.22.1  thorpej 	rolb	#2,%d1
    775  1.2.22.1  thorpej 	andib	#0xC0,%d1		| Get top 2 bits for third byte
    776       1.1   scottr rsTagNyb4:
    777  1.2.22.1  thorpej 	moveb	%a0@,%d3		| Get third 6 bit nibble
    778       1.1   scottr 	bpl	rsTagNyb4
    779  1.2.22.1  thorpej 	orb	%a2@(0,%d3),%d1		| remap it and complete byte
    780  1.2.22.1  thorpej 	eorb	%d6,%d1
    781  1.2.22.1  thorpej 	moveb	%d1,%a4@+		| Store tag byte
    782  1.2.22.1  thorpej 	addxb	%d1,%d7
    783       1.1   scottr 
    784  1.2.22.1  thorpej 	subqw	#3,%d4			| Update byte counter (four 6&2 encoded
    785       1.1   scottr 	bpl	rsTags			| disk bytes make three data bytes).
    786       1.2   scottr 
    787       1.1   scottr 	/*
    788       1.1   scottr 	 * Jetzt sind wir hier...
    789       1.1   scottr 	 * ...und Thomas D. hat noch was zu sagen...
    790       1.1   scottr 	 *
    791       1.1   scottr 	 * We begin to read in the actual sector data.
    792       1.2   scottr 	 * Compare sector # to what we wanted: If it matches, read directly
    793       1.2   scottr 	 * to buffer, else read to track cache.
    794       1.1   scottr 	 */
    795  1.2.22.1  thorpej 	movew	#0x01FE,%d4		| Loop counter
    796  1.2.22.1  thorpej 	moveq	#0,%d1			| Clear %d1
    797  1.2.22.1  thorpej 	moveb	%a6@(-7),%d1		| Get sector# we have read
    798  1.2.22.1  thorpej 	cmpb	%a6@(-5),%d1		| Compare to the sector# we want
    799       1.2   scottr 	bne	rsToCache
    800  1.2.22.1  thorpej 	movel	%a6@(o_buf),%a4		| Sector data buffer
    801       1.2   scottr 	bra	rsData
    802       1.2   scottr rsToCache:
    803  1.2.22.1  thorpej 	movel	%a6@(o_rslots),%a4	| Base address of slot array
    804  1.2.22.1  thorpej 	lslw	#3,%d1			| sizeof cylCacheSlot_t is 8 bytes
    805  1.2.22.1  thorpej 	movel	#-1,%a4@(o_valid,%d1)
    806  1.2.22.1  thorpej 	movel	%a4@(o_secbuf,%d1),%a4	| and get its buffer ptr
    807       1.1   scottr rsData:
    808       1.1   scottr rsDatNyb1:
    809  1.2.22.1  thorpej 	moveb	%a0@,%d3		| Get 2 bit nibbles
    810       1.1   scottr 	bpl	rsDatNyb1
    811  1.2.22.1  thorpej 	moveb	%a2@(0,%d3),%d1		| Remap disk byte
    812  1.2.22.1  thorpej 	rolb	#2,%d1
    813  1.2.22.1  thorpej 	moveb	%d1,%d2
    814  1.2.22.1  thorpej 	andib	#0xC0,%d2		| Get top 2 bits for first byte
    815       1.1   scottr rsDatNyb2:
    816  1.2.22.1  thorpej 	moveb	%a0@,%d3		| Get first 6 bit nibble
    817       1.1   scottr 	bpl	rsDatNyb2
    818  1.2.22.1  thorpej 	orb	%a2@(0,%d3),%d2		| Remap it and complete first byte
    819       1.1   scottr 
    820  1.2.22.1  thorpej 	moveb	%d7,%d3			| The X flag bit (a copy of the carry
    821  1.2.22.1  thorpej 	addb	%d7,%d3			| flag) is added with the next addx
    822       1.1   scottr 
    823  1.2.22.1  thorpej 	rolb	#1,%d7
    824  1.2.22.1  thorpej 	eorb	%d7,%d2
    825  1.2.22.1  thorpej 	moveb	%d2,%a4@+		| Store data byte
    826  1.2.22.1  thorpej 	addxb	%d2,%d5			| See above
    827  1.2.22.1  thorpej 
    828  1.2.22.1  thorpej 	rolb	#2,%d1
    829  1.2.22.1  thorpej 	moveb	%d1,%d2
    830  1.2.22.1  thorpej 	andib	#0xC0,%d2		| Get top 2 bits for second byte
    831       1.1   scottr rsDatNyb3:
    832  1.2.22.1  thorpej 	moveb	%a0@,%d3		| Get second 6 bit nibble
    833       1.1   scottr 	bpl	rsDatNyb3
    834  1.2.22.1  thorpej 	orb	%a2@(0,%d3),%d2		| Remap it and complete byte
    835  1.2.22.1  thorpej 	eorb	%d5,%d2
    836  1.2.22.1  thorpej 	moveb	%d2,%a4@+		| Store data byte
    837  1.2.22.1  thorpej 	addxb	%d2,%d6
    838  1.2.22.1  thorpej 	tstw	%d4
    839       1.1   scottr 	beq	rsCkSum			| Data read, continue with checksums
    840       1.1   scottr 
    841  1.2.22.1  thorpej 	rolb	#2,%d1
    842  1.2.22.1  thorpej 	andib	#0xC0,%d1		| Get top 2 bits for third byte
    843       1.1   scottr rsDatNyb4:
    844  1.2.22.1  thorpej 	moveb	%a0@,%d3		| Get third 6 bit nibble
    845       1.1   scottr 	bpl	rsDatNyb4
    846  1.2.22.1  thorpej 	orb	%a2@(0,%d3),%d1		| Remap it and complete byte
    847  1.2.22.1  thorpej 	eorb	%d6,%d1
    848  1.2.22.1  thorpej 	moveb	%d1,%a4@+		| Store data byte
    849  1.2.22.1  thorpej 	addxb	%d1,%d7
    850  1.2.22.1  thorpej 	subqw	#3,%d4			| Update byte counter
    851       1.1   scottr 	bra	rsData
    852       1.1   scottr 
    853       1.1   scottr 	/*
    854       1.1   scottr 	 * Next read checksum bytes
    855       1.1   scottr 	 * While reading the sector data, three separate checksums are
    856  1.2.22.1  thorpej 	 * maintained in %D5/%D6/%D7 for the 1st/2nd/3rd data byte of
    857  1.2.22.1  thorpej 	 * each group.
    858       1.1   scottr 	 */
    859       1.1   scottr rsCkSum:
    860       1.1   scottr rsCkS1:
    861  1.2.22.1  thorpej 	moveb	%a0@,%d3		| Get 2 bit nibbles
    862       1.1   scottr 	bpl	rsCkS1
    863  1.2.22.1  thorpej 	moveb	%a2@(0,%d3),%d1		| Remap disk byte
    864       1.1   scottr 	bmi	rsBadCkSum		| Fault! (Bad read)
    865  1.2.22.1  thorpej 	rolb	#2,%d1
    866  1.2.22.1  thorpej 	moveb	%d1,%d2
    867  1.2.22.1  thorpej 	andib	#0xC0,%d2		| Get top 2 bits for first byte
    868       1.1   scottr rsCkS2:
    869  1.2.22.1  thorpej 	moveb	%a0@,%d3		| Get first 6 bit nibble
    870       1.1   scottr 	bpl	rsCkS2
    871  1.2.22.1  thorpej 	moveb	%a2@(0,%d3),%d3		| and remap it
    872       1.1   scottr 	bmi	rsBadCkSum		| Fault! ( > 0x3f is bad read)
    873  1.2.22.1  thorpej 	orb	%d3,%d2			| Merge 6&2
    874  1.2.22.1  thorpej 	cmpb	%d2,%d5			| Compare first checksum to %D5
    875       1.1   scottr 	bne	rsBadCkSum		| Fault! (Checksum)
    876       1.1   scottr 
    877  1.2.22.1  thorpej 	rolb	#2,%d1
    878  1.2.22.1  thorpej 	moveb	%d1,%d2
    879  1.2.22.1  thorpej 	andib	#0xC0,%d2		| Get top 2 bits for second byte
    880       1.1   scottr rsCkS3:
    881  1.2.22.1  thorpej 	moveb	%a0@,%d3		| Get second 6 bit nibble
    882       1.1   scottr 	bpl	rsCkS3
    883  1.2.22.1  thorpej 	moveb	%a2@(0,%d3),%d3		| and remap it
    884       1.1   scottr 	bmi	rsBadCkSum		| Fault! (Bad read)
    885  1.2.22.1  thorpej 	orb	%d3,%d2			| Merge 6&2
    886  1.2.22.1  thorpej 	cmpb	%d2,%d6			| Compare second checksum to %D6
    887       1.1   scottr 	bne	rsBadCkSum		| Fault! (Checksum)
    888       1.1   scottr 
    889  1.2.22.1  thorpej 	rolb	#2,%d1
    890  1.2.22.1  thorpej 	andib	#0xC0,%d1		| Get top 2 bits for second byte
    891       1.1   scottr rsCkS4:
    892  1.2.22.1  thorpej 	moveb	%a0@,%d3		| Get third 6 bit nibble
    893       1.1   scottr 	bpl	rsCkS4
    894  1.2.22.1  thorpej 	moveb	%a2@(0,%d3),%d3		| and remap it
    895       1.1   scottr 	bmi	rsBadCkSum		| Fault! (Bad read)
    896  1.2.22.1  thorpej 	orb	%d3,%d1			| Merge 6&2
    897  1.2.22.1  thorpej 	cmpb	%d1,%d7			| Compare third checksum to %D7
    898       1.1   scottr 	beq	rsLdOut			| Fault! (Checksum)
    899       1.1   scottr 
    900       1.1   scottr rsBadCkSum:
    901  1.2.22.1  thorpej 	moveq	#badDCkSum,%d0		| Bad data mark checksum
    902       1.1   scottr 	bra	rsDone
    903       1.1   scottr 
    904       1.1   scottr rsBadDBtSlp:
    905  1.2.22.1  thorpej 	moveq	#badDBtSlp,%d0		| One of the data mark bit slip
    906       1.1   scottr 	bra	rsDone			| nibbles was incorrect
    907       1.1   scottr 
    908       1.1   scottr 	/*
    909       1.1   scottr 	 * We have gotten the checksums allright, now look for the
    910       1.1   scottr 	 * sector data lead-out 'DE AA'
    911  1.2.22.1  thorpej 	 * (We have %a3 still pointing to 'dataLeadOut'; this part of the
    912       1.1   scottr 	 * table is used for writing to disk, too.)
    913       1.1   scottr 	 */
    914       1.1   scottr rsLdOut:
    915  1.2.22.1  thorpej 	moveq	#1,%d4			| Is two bytes long {1,0}
    916       1.1   scottr rsLdOut1:
    917  1.2.22.1  thorpej 	moveb	%a0@,%d3		| Get token
    918       1.1   scottr 	bpl	rsLdOut1
    919  1.2.22.1  thorpej 	cmpb	%a3@+,%d3
    920       1.1   scottr 	bne	rsBadDBtSlp		| Fault!
    921  1.2.22.1  thorpej 	dbra	%d4,rsLdOut1
    922  1.2.22.1  thorpej 	moveq	#0,%d0			| OK.
    923       1.2   scottr 
    924       1.2   scottr 	/*
    925       1.2   scottr 	 * See if we got the sector we wanted. If not, and no error
    926       1.2   scottr 	 * occurred, mark buffer valid. Else ignore the sector.
    927       1.2   scottr 	 * Then, read on.
    928       1.2   scottr 	 */
    929       1.1   scottr rsDone:
    930  1.2.22.1  thorpej 	movel	%a6@(o_hdr),%a4		| Addr of sector header struct
    931  1.2.22.1  thorpej 	moveb	%a4@(o_sector),%d1	| Get # of sector we have just read
    932  1.2.22.1  thorpej 	cmpb	%a6@(-5),%d1		| Compare to the sector we want
    933       1.2   scottr 	beq	rsAllDone
    934       1.2   scottr 
    935  1.2.22.1  thorpej 	tstb	%d0			| Any error? Simply ignore data
    936       1.2   scottr 	beq	rsBufValid
    937  1.2.22.1  thorpej 	lslw	#3,%d1			| sizeof cylCacheSlot_t is 8 bytes
    938  1.2.22.1  thorpej 	movel	%a6@(o_rslots),%a4
    939  1.2.22.1  thorpej 	clrl	%a4@(o_valid,%d1)	| Mark buffer content "invalid"
    940       1.2   scottr 
    941       1.2   scottr rsBufValid:
    942  1.2.22.1  thorpej 	subqb	#1,%a6@(-6)		| max. retries
    943       1.2   scottr 	bne	rsNextSect
    944       1.2   scottr 					| Sector not found, but
    945  1.2.22.1  thorpej 	tstb	%d0			| don't set error code if we
    946       1.2   scottr 	bne	rsAllDone		| already have one.
    947  1.2.22.1  thorpej 	moveq	#sectNFErr,%d0
    948       1.2   scottr rsAllDone:
    949  1.2.22.1  thorpej 	movew	%a6@(-2),%sr		| Restore interrupt mask
    950  1.2.22.1  thorpej 	moveml	%sp@+,%d1-%d7/%a0-%a5
    951  1.2.22.1  thorpej 	unlk	%a6
    952       1.2   scottr 	rts
    953       1.1   scottr 
    954       1.1   scottr 
    955       1.1   scottr /*
    956       1.1   scottr  * iwmWriteSector -- encode and write data to the specified sector.
    957       1.1   scottr  *
    958       1.1   scottr  * TODO:	Poll SCC as long as interrupts are disabled (see top comment)
    959       1.1   scottr  *		Understand and document the checksum algorithm!
    960       1.1   scottr  *
    961       1.2   scottr  *		XXX Use registers more efficiently
    962       1.2   scottr  *
    963  1.2.22.1  thorpej  * Parameters:	%fp+8	l	Address of sector header struct (I/O)
    964  1.2.22.1  thorpej  *		%fp+12	l	Address of cache buffer ptr array
    965  1.2.22.1  thorpej  * Returns:	%d0		result code
    966  1.2.22.1  thorpej  *
    967  1.2.22.1  thorpej  * Local:	%fp-2	w	CPU status register
    968  1.2.22.1  thorpej  *		%fp-3	b	side,
    969  1.2.22.1  thorpej  *		%fp-4	b	track,
    970  1.2.22.1  thorpej  *		%fp-5	b	sector wanted
    971  1.2.22.1  thorpej  *		%fp-6	b	retry count
    972  1.2.22.1  thorpej  *		%fp-10	b	current slot
    973       1.1   scottr  */
    974       1.1   scottr ENTRY(iwmWriteSector)
    975  1.2.22.1  thorpej 	link	%a6,#-10
    976  1.2.22.1  thorpej 	moveml	%d1-%d7/%a0-%a5,%sp@-
    977       1.1   scottr 
    978  1.2.22.1  thorpej  	movel	_C_LABEL(Via1Base),%a1
    979  1.2.22.1  thorpej 	movel	%a6@(o_hdr),%a4		| Addr of sector header struct
    980       1.1   scottr 
    981  1.2.22.1  thorpej 	moveb	%a4@+,%a6@(-3)		| Save side bit,
    982  1.2.22.1  thorpej 	moveb	%a4@+,%a6@(-4)		| track#,
    983  1.2.22.1  thorpej 	moveb	%a4@,%a6@(-5)		| sector#
    984  1.2.22.1  thorpej 	moveb	#maxGCRSectors,%a6@(-6)	| Max. retry count
    985       1.1   scottr 
    986  1.2.22.1  thorpej 	movew	%sr,%a6@(-2)		| Save CPU status register
    987  1.2.22.1  thorpej 	oriw	#0x0600,%sr		| Block all interrupts
    988       1.1   scottr 
    989       1.2   scottr wsNextSect:
    990  1.2.22.1  thorpej 	movel	%a6@(o_hdr),%a4
    991       1.1   scottr 	bsr	readSectHdr		| Get next available sector header
    992       1.2   scottr 	bne	wsAllDone		| Return if error
    993       1.1   scottr 
    994       1.1   scottr 	/*
    995       1.1   scottr 	 * Is this the right track & side? If not, return with error
    996       1.1   scottr 	 */
    997  1.2.22.1  thorpej 	movel	%a6@(o_hdr),%a4		| Sector header struct
    998       1.1   scottr 
    999  1.2.22.1  thorpej 	moveb	%a4@(o_side),%d1	| Get side#
   1000  1.2.22.1  thorpej 	lsrb	#3,%d1			| "Normalize" side bit...
   1001  1.2.22.1  thorpej 	andb	#1,%d1
   1002  1.2.22.1  thorpej 	moveb	%a6@(-3),%d2		| Get wanted side
   1003  1.2.22.1  thorpej 	eorb	%d1,%d2			| Compare side bits
   1004       1.1   scottr 	bne	wsSeekErr
   1005       1.1   scottr 
   1006  1.2.22.1  thorpej 	moveb	%a6@(-4),%d1		| Get wanted track#
   1007  1.2.22.1  thorpej 	cmpb	%a4@(o_track),%d1	| Compare to the read header
   1008       1.1   scottr 	beq	wsCompSect
   1009       1.1   scottr 
   1010       1.1   scottr wsSeekErr:
   1011  1.2.22.1  thorpej 	moveq	#seekErr,%d0		| Wrong track or side
   1012       1.2   scottr 	bra	wsAllDone
   1013       1.1   scottr 
   1014       1.1   scottr 	/*
   1015       1.2   scottr 	 * Look up the current sector number in the cache.
   1016       1.2   scottr 	 * If the buffer is dirty ("valid"), write it to disk. If not,
   1017       1.2   scottr 	 * loop over all the slots and return if all of them are clean.
   1018       1.2   scottr 	 *
   1019       1.2   scottr 	 * Alternatively, we could decrement a "dirty sectors" counter here.
   1020       1.1   scottr 	 */
   1021       1.1   scottr wsCompSect:
   1022  1.2.22.1  thorpej 	moveq	#0,%d1			| Clear register
   1023  1.2.22.1  thorpej 	moveb	%a4@(o_sector),%d1	| get the # of header read
   1024  1.2.22.1  thorpej 	lslw	#3,%d1			| sizeof cylCacheSlot_t is 8 bytes
   1025  1.2.22.1  thorpej 	movel	%a6@(o_wslots),%a4
   1026  1.2.22.1  thorpej 	tstl	%a4@(o_valid,%d1)	| Sector dirty?
   1027       1.2   scottr 	bne	wsBufDirty
   1028       1.2   scottr 
   1029  1.2.22.1  thorpej 	moveq	#maxGCRSectors-1,%d2	| Any dirty sectors left?
   1030       1.2   scottr wsChkDty:
   1031  1.2.22.1  thorpej 	movew	%d2,%d1
   1032  1.2.22.1  thorpej 	lslw	#3,%d1			| sizeof cylCacheSlot_t is 8 bytes
   1033  1.2.22.1  thorpej 	tstl	%a4@(o_valid,%d1)
   1034       1.2   scottr 	bne	wsNextSect		| Sector dirty?
   1035  1.2.22.1  thorpej 	dbra	%d2,wsChkDty
   1036       1.2   scottr 
   1037       1.2   scottr 	bra	wsAllDone		| We are through with this track.
   1038       1.2   scottr 
   1039       1.1   scottr 
   1040       1.1   scottr 	/*
   1041       1.1   scottr 	 * Write sync pattern and sector data lead-in 'D5 AA'. The
   1042       1.1   scottr 	 * missing 'AD' is made up by piping 0x0B through the nibble
   1043       1.1   scottr 	 * table (toDisk).
   1044       1.1   scottr 	 *
   1045       1.1   scottr 	 * To set up IWM for writing:
   1046       1.1   scottr 	 *
   1047       1.1   scottr 	 * access q6H & write first byte to q7H.
   1048       1.1   scottr 	 * Then check bit 7 of q6L (status reg) for 'IWM ready'
   1049       1.1   scottr 	 * and write subsequent bytes to q6H.
   1050       1.1   scottr 	 *
   1051       1.1   scottr 	 * Registers:
   1052  1.2.22.1  thorpej 	 *	%a0	IWM base address (later: data register)
   1053  1.2.22.1  thorpej 	 *	%a1	Via1Base
   1054  1.2.22.1  thorpej 	 *	%a2	IWM handshake register
   1055  1.2.22.1  thorpej 	 *	%a3	data (tags buffer, data buffer)
   1056  1.2.22.1  thorpej 	 *	%a4	Sync pattern, 'toDisk' translation table
   1057       1.1   scottr 	 */
   1058       1.2   scottr wsBufDirty:
   1059  1.2.22.1  thorpej 	movel	_C_LABEL(IWMBase),%a0
   1060  1.2.22.1  thorpej 	lea	%a4@(0,%d1),%a3
   1061  1.2.22.1  thorpej 	movel	%a3,%a6@(-10)		| Save ptr to current slot
   1062  1.2.22.1  thorpej 	tstb	%a0@(q6H)		| Enable writing to disk
   1063  1.2.22.1  thorpej 	movel	%a6@(o_hdr),%a4		| Sector header struct
   1064  1.2.22.1  thorpej 	lea	%a4@(o_Tags),%a3	| Point %a3 to tags buffer
   1065  1.2.22.1  thorpej 	lea	syncPattern,%a4
   1066  1.2.22.1  thorpej 
   1067  1.2.22.1  thorpej 	moveb	%a4@+,%a0@(q7H)		| Write first sync byte
   1068  1.2.22.1  thorpej 	lea	%a0@(q6L),%a2		| Point %a2 to handshake register
   1069  1.2.22.1  thorpej 	lea	%a0@(q6H),%a0		| Point %a0 to IWM data register
   1070  1.2.22.1  thorpej 
   1071  1.2.22.1  thorpej 	moveq	#6,%d0			| Loop counter for sync bytes
   1072  1.2.22.1  thorpej 	moveq	#0,%d2
   1073  1.2.22.1  thorpej 	moveq	#0,%d3
   1074  1.2.22.1  thorpej 	movel	#0x02010009,%d4		| Loop counters for tag/sector data
   1075       1.1   scottr 
   1076       1.1   scottr 	/*
   1077       1.1   scottr 	 * Write 5 sync bytes and first byte of sector data lead-in
   1078       1.1   scottr 	 */
   1079       1.1   scottr wsLeadIn:
   1080  1.2.22.1  thorpej 	moveb	%a4@+,%d1		| Get next sync byte
   1081       1.1   scottr wsLI1:
   1082  1.2.22.1  thorpej 	tstb	%a2@			| IWM ready?
   1083       1.1   scottr 	bpl	wsLI1
   1084  1.2.22.1  thorpej 	moveb	%d1,%a0@		| Write it to disk
   1085  1.2.22.1  thorpej 	subqw	#1,%d0
   1086       1.1   scottr 	bne	wsLeadIn
   1087       1.1   scottr 
   1088  1.2.22.1  thorpej 	moveb	%a4@+,%d1		| Write 2nd byte of sector lead-in
   1089  1.2.22.1  thorpej 	lea	toDisk,%a4		| Point %a4 to nibble translation table
   1090       1.1   scottr wsLI2:
   1091  1.2.22.1  thorpej 	tstb	%a2@			| IWM ready?
   1092       1.1   scottr 	bpl	wsLI2
   1093  1.2.22.1  thorpej 	moveb	%d1,%a0@		| Write it to disk
   1094       1.1   scottr 
   1095  1.2.22.1  thorpej 	moveq	#0,%d5			| Clear checksum registers
   1096  1.2.22.1  thorpej 	moveq	#0,%d6
   1097  1.2.22.1  thorpej 	moveq	#0,%d7
   1098       1.1   scottr 
   1099  1.2.22.1  thorpej 	moveq	#0x0B,%d1		| 3rd byte of sector data lead-in
   1100       1.1   scottr 					| (Gets translated to 0xAD)
   1101  1.2.22.1  thorpej 	moveb	%a3@+,%d2		| Get 1st byte from tags buffer
   1102       1.1   scottr 	bra	wsDataEntry
   1103       1.1   scottr 
   1104       1.1   scottr 	/*
   1105       1.1   scottr 	 * The following loop reads the content of the tags buffer (12 bytes)
   1106       1.1   scottr 	 * and the data buffer (512 bytes).
   1107       1.1   scottr 	 * Each pass reads out three bytes and
   1108       1.1   scottr 	 * a) splits them 6&2 into three 6 bit nibbles and a fourth byte
   1109       1.1   scottr 	 *    consisting of the three 2 bit nibbles
   1110       1.1   scottr 	 * b) encodes the nibbles with a table to disk bytes (bit 7 set, no
   1111       1.1   scottr 	 *    more than two consecutive zero bits) and writes them to disk as
   1112       1.1   scottr 	 *
   1113       1.1   scottr 	 *    00mmnnoo		fragment 2 bit nibbles
   1114       1.1   scottr 	 *    00mmmmmm		6 bit nibble -- first byte
   1115       1.1   scottr 	 *    00nnnnnn		6 bit nibble -- second byte
   1116       1.1   scottr 	 *    00oooooo		6 bit nibble -- third byte
   1117       1.1   scottr 	 *
   1118       1.1   scottr 	 * c) adds up three 8 bit checksums, one for each of the bytes written.
   1119       1.1   scottr 	 */
   1120       1.2   scottr wsSD1:
   1121  1.2.22.1  thorpej 	movel	%a6@(-10),%a3		| Get ptr to current slot
   1122  1.2.22.1  thorpej 	movel	%a3@(o_secbuf),%a3	| Get start of sector data buffer
   1123       1.1   scottr 
   1124       1.1   scottr wsData:
   1125  1.2.22.1  thorpej 	addxb	%d2,%d7
   1126  1.2.22.1  thorpej 	eorb	%d6,%d2
   1127  1.2.22.1  thorpej 	moveb	%d2,%d3
   1128  1.2.22.1  thorpej 	lsrw	#6,%d3			| Put 2 bit nibbles into place
   1129       1.1   scottr wsRDY01:
   1130  1.2.22.1  thorpej 	tstb	%a2@			| IWM ready?
   1131       1.1   scottr 	bpl	wsRDY01
   1132  1.2.22.1  thorpej 	moveb	%a4@(0,%d3),%a0@	| Translate nibble and write
   1133  1.2.22.1  thorpej 	subqw	#3,%d4			| Update counter
   1134  1.2.22.1  thorpej 	moveb	%d7,%d3
   1135  1.2.22.1  thorpej 	addb	%d7,%d3			| Set X flag (??)
   1136  1.2.22.1  thorpej 	rolb	#1,%d7
   1137  1.2.22.1  thorpej 	andib	#0x3F,%d0
   1138       1.1   scottr wsRDY02:
   1139  1.2.22.1  thorpej 	tstb	%a2@			| IWM ready?
   1140       1.1   scottr 	bpl	wsRDY02
   1141  1.2.22.1  thorpej 	moveb	%a4@(0,%d0),%a0@	| Translate nibble and write
   1142       1.1   scottr 
   1143       1.1   scottr 	/*
   1144       1.1   scottr 	 * We enter with the last byte of the sector data lead-in
   1145  1.2.22.1  thorpej 	 * between our teeth (%D1, that is).
   1146       1.1   scottr 	 */
   1147       1.1   scottr wsDataEntry:
   1148  1.2.22.1  thorpej 	moveb	%a3@+,%d0		| Get first byte
   1149  1.2.22.1  thorpej 	addxb	%d0,%d5
   1150  1.2.22.1  thorpej 	eorb	%d7,%d0
   1151  1.2.22.1  thorpej 	moveb	%d0,%d3			| Keep top two bits
   1152  1.2.22.1  thorpej 	rolw	#2,%d3			| by shifting them to MSByte
   1153  1.2.22.1  thorpej 	andib	#0x3F,%d1
   1154       1.1   scottr wsRDY03:
   1155  1.2.22.1  thorpej 	tstb	%a2@			| IWM ready?
   1156       1.1   scottr 	bpl	wsRDY03
   1157  1.2.22.1  thorpej 	moveb	%a4@(0,%d1),%a0@	| Translate nibble and write
   1158       1.1   scottr 
   1159  1.2.22.1  thorpej 	moveb	%a3@+,%d1			| Get second byte
   1160  1.2.22.1  thorpej 	addxb	%d1,%d6
   1161  1.2.22.1  thorpej 	eorb	%d5,%d1
   1162  1.2.22.1  thorpej 	moveb	%d1,%d3			| Keep top two bits
   1163  1.2.22.1  thorpej 	rolw	#2,%d3			| by shifting them to MSByte
   1164  1.2.22.1  thorpej 	andib	#0x3F,%d2
   1165       1.1   scottr wsRDY04:
   1166  1.2.22.1  thorpej 	tstb	%a2@			| IWM ready?
   1167       1.1   scottr 	bpl	wsRDY04
   1168  1.2.22.1  thorpej 	moveb	%a4@(0,%d2),%a0@	| Translate nibble and write
   1169       1.2   scottr 
   1170       1.1   scottr 	/*
   1171       1.1   scottr 	 * XXX We have a classic off-by-one error here: the last access
   1172       1.1   scottr 	 * reaches beyond the data buffer which bombs with memory
   1173       1.1   scottr 	 * protection. The value read isn't used anyway...
   1174       1.1   scottr 	 * Hopefully there is enough time for an additional check
   1175       1.1   scottr 	 * (exit the last loop cycle before the buffer access).
   1176       1.1   scottr 	 */
   1177  1.2.22.1  thorpej 	tstl	%d4			| Last loop cycle?
   1178       1.1   scottr 	beq	wsSDDone		| Then get out while we can.
   1179       1.1   scottr 
   1180  1.2.22.1  thorpej 	moveb	%a3@+,%d2		| Get third byte
   1181  1.2.22.1  thorpej 	tstw	%d4			| First write tag buffer,...
   1182       1.1   scottr 	bne	wsData
   1183       1.1   scottr 
   1184  1.2.22.1  thorpej 	swap	%d4			| ...then write data buffer
   1185       1.1   scottr 	bne	wsSD1
   1186       1.1   scottr 
   1187       1.1   scottr 	/*
   1188       1.1   scottr 	 * Write nibbles for last 2 bytes, then
   1189       1.1   scottr 	 * split checksum bytes in 6&2 and write them to disk
   1190       1.1   scottr 	 */
   1191       1.1   scottr wsSDDone:
   1192  1.2.22.1  thorpej 	clrb	%d3			| No 513th byte
   1193  1.2.22.1  thorpej 	lsrw	#6,%d3			| Set up 2 bit nibbles
   1194       1.1   scottr wsRDY05:
   1195  1.2.22.1  thorpej 	tstb	%a2@			| IWM ready?
   1196       1.1   scottr 	bpl	wsRDY05
   1197  1.2.22.1  thorpej 	moveb	%a4@(0,%d3),%a0@	| Write fragments
   1198  1.2.22.1  thorpej 	moveb	%d5,%d3
   1199  1.2.22.1  thorpej 	rolw	#2,%d3
   1200  1.2.22.1  thorpej 	moveb	%d6,%d3
   1201  1.2.22.1  thorpej 	rolw	#2,%d3
   1202  1.2.22.1  thorpej 	andib	#0x3F,%d0
   1203       1.1   scottr wsRDY06:
   1204  1.2.22.1  thorpej 	tstb	%a2@			| IWM ready?
   1205       1.1   scottr 	bpl	wsRDY06
   1206  1.2.22.1  thorpej 	moveb	%a4@(0,%d0),%a0@	| Write 511th byte
   1207  1.2.22.1  thorpej 	andib	#0x3F,%d1
   1208       1.1   scottr wsRDY07:
   1209  1.2.22.1  thorpej 	tstb	%a2@			| IWM ready?
   1210       1.1   scottr 	bpl	wsRDY07
   1211  1.2.22.1  thorpej 	moveb	%a4@(0,%d1),%a0@	| write 512th byte
   1212  1.2.22.1  thorpej 	moveb	%d7,%d3
   1213  1.2.22.1  thorpej 	lsrw	#6,%d3			| Get fragments ready
   1214       1.1   scottr wsRDY08:
   1215  1.2.22.1  thorpej 	tstb	%a2@			| IWM ready?
   1216       1.1   scottr 	bpl	wsRDY08
   1217  1.2.22.1  thorpej 	moveb	%a4@(0,%d3),%a0@	| Write fragments
   1218  1.2.22.1  thorpej 	andib	#0x3F,%d5
   1219       1.1   scottr wsRDY09:
   1220  1.2.22.1  thorpej 	tstb	%a2@			| IWM ready?
   1221       1.1   scottr 	bpl	wsRDY09
   1222  1.2.22.1  thorpej 	moveb	%a4@(0,%d5),%a0@	| Write first checksum byte
   1223  1.2.22.1  thorpej 	andib	#0x3F,%D6
   1224       1.1   scottr wsRDY10:
   1225  1.2.22.1  thorpej 	tstb	%a2@			| IWM ready?
   1226       1.1   scottr 	bpl	wsRDY10
   1227  1.2.22.1  thorpej 	moveb	%a4@(0,%d6),%a0@	| Write second checksum byte
   1228  1.2.22.1  thorpej 	andib	#0x3F,%d7
   1229       1.1   scottr wsRDY11:
   1230  1.2.22.1  thorpej 	tstb	%a2@			| IWM ready?
   1231       1.1   scottr 	bpl	wsRDY11
   1232  1.2.22.1  thorpej 	moveb	%a4@(0,%d7),%a0@	| Write third checksum byte
   1233       1.1   scottr 
   1234       1.1   scottr 	/*
   1235       1.1   scottr 	 * Write sector data lead-out
   1236       1.1   scottr 	 */
   1237  1.2.22.1  thorpej 	lea	dataLeadOut,%a4		| Sector data lead-out
   1238  1.2.22.1  thorpej 	moveq	#3,%d2			| Four bytes long {3,2,1,0}
   1239       1.1   scottr wsLeadOut:
   1240  1.2.22.1  thorpej 	moveb	%a2@,%d1		| IWM ready?
   1241       1.1   scottr 	bpl	wsLeadOut
   1242  1.2.22.1  thorpej 	moveb	%a4@+,%a0@		| Write lead-out
   1243  1.2.22.1  thorpej 	dbf	%d2,wsLeadOut
   1244       1.1   scottr 
   1245  1.2.22.1  thorpej 	moveq	#0,%d0
   1246  1.2.22.1  thorpej 	btst	#6,%d1			| Check IWM underrun bit
   1247       1.1   scottr 	bne	wsNoErr
   1248       1.1   scottr 
   1249  1.2.22.1  thorpej 	moveq	#wrUnderRun,%d0		| Could not write
   1250       1.1   scottr 					| fast enough to keep up with IWM
   1251       1.1   scottr wsNoErr:
   1252  1.2.22.1  thorpej 	tstb	%a0@(0x0200)		| q7L -- Write OFF
   1253       1.1   scottr 
   1254       1.1   scottr wsDone:
   1255  1.2.22.1  thorpej 	tstb	%d0			| Any error? Simply retry
   1256       1.2   scottr 	bne	wsBufInvalid
   1257       1.2   scottr 
   1258  1.2.22.1  thorpej 	movel	%a6@(-10),%a4		| Else, get ptr to current slot
   1259  1.2.22.1  thorpej 	clrl	%a4@(o_valid)		| Mark current buffer "clean"
   1260       1.2   scottr 	bra	wsNextSect
   1261       1.2   scottr 
   1262       1.2   scottr wsBufInvalid:
   1263  1.2.22.1  thorpej 	subqb	#1,%a6@(-6)		| retries
   1264       1.2   scottr 	bne	wsNextSect
   1265       1.2   scottr 					| Sector not found, but
   1266  1.2.22.1  thorpej 	tstb	%d0			| don't set error code if we
   1267       1.2   scottr 	bne	wsAllDone		| already have one.
   1268  1.2.22.1  thorpej 	moveq	#sectNFErr,%d0
   1269       1.2   scottr 
   1270       1.2   scottr wsAllDone:
   1271  1.2.22.1  thorpej 	movew	%a6@(-2),%sr		| Restore interrupt mask
   1272  1.2.22.1  thorpej 	moveml	%sp@+,%d1-%d7/%a0-%a5
   1273  1.2.22.1  thorpej 	unlk	%a6
   1274       1.1   scottr 	rts
   1275       1.1   scottr 
   1276       1.1   scottr 
   1277       1.1   scottr 
   1278       1.1   scottr /**
   1279       1.1   scottr  **	Local functions
   1280       1.1   scottr  **/
   1281       1.1   scottr 
   1282       1.1   scottr /*
   1283       1.1   scottr  * iwmDelay
   1284       1.1   scottr  *
   1285       1.1   scottr  * In-kernel calls to delay() in mac68k/clock.c bomb
   1286       1.1   scottr  *
   1287  1.2.22.1  thorpej  * Parameters:	%d0	delay in milliseconds
   1288  1.2.22.1  thorpej  * Trashes:	%d0, %d1
   1289       1.1   scottr  * Returns:	-
   1290       1.1   scottr  */
   1291       1.1   scottr iwmDelay:
   1292       1.1   scottr 	/* TimeDBRA is ~8K for 040/33 machines, so we need nested loops */
   1293  1.2.22.1  thorpej id00:	movew	_C_LABEL(TimeDBRA),%d1	| dbra loops per ms
   1294  1.2.22.1  thorpej id01:	dbra	%d1,id01		|
   1295  1.2.22.1  thorpej 	dbra	%d0,id00
   1296       1.1   scottr 	rts
   1297       1.1   scottr 
   1298       1.1   scottr 
   1299       1.1   scottr /*
   1300       1.1   scottr  * selDriveReg -- Select drive status/control register
   1301       1.1   scottr  *
   1302  1.2.22.1  thorpej  * Parameters:	%d0	register #
   1303       1.1   scottr  *			(bit 0 - CA2, bit 1 - SEL, bit 2 - CA0, bit 3 - CA1)
   1304  1.2.22.1  thorpej  *		%a0	IWM base address
   1305  1.2.22.1  thorpej  *		%a1	VIA base address
   1306  1.2.22.1  thorpej  * Returns:	%d0	register # (unchanged)
   1307       1.1   scottr  */
   1308       1.1   scottr selDriveReg:
   1309  1.2.22.1  thorpej 	tstb	%a0@(ph0H)		| default CA0 to 1 (says IM III)
   1310  1.2.22.1  thorpej 	tstb	%a0@(ph1H)		| default CA1 to 1
   1311       1.1   scottr 
   1312  1.2.22.1  thorpej 	btst	#0,%d0			| bit 0 set => CA2 on
   1313       1.1   scottr 	beq	se00
   1314  1.2.22.1  thorpej 	tstb	%a0@(ph2H)
   1315       1.1   scottr 	bra	se01
   1316       1.1   scottr se00:
   1317  1.2.22.1  thorpej 	tstb	%a0@(ph2L)
   1318       1.1   scottr 
   1319       1.1   scottr se01:
   1320  1.2.22.1  thorpej 	btst	#1,%d0			| bit 1 set => SEL on (VIA 1)
   1321       1.1   scottr 	beq	se02
   1322  1.2.22.1  thorpej 	bset	#vHeadSel,%a1@(vBufA)
   1323       1.1   scottr 	bra	se03
   1324       1.1   scottr se02:
   1325  1.2.22.1  thorpej 	bclr	#vHeadSel,%a1@(vBufA)
   1326       1.1   scottr 
   1327       1.1   scottr se03:
   1328  1.2.22.1  thorpej 	btst	#2,%d0			| bit 2 set => CA0 on
   1329       1.1   scottr 	bne	se04
   1330  1.2.22.1  thorpej 	tstb	%a0@(ph0L)
   1331       1.1   scottr 
   1332       1.1   scottr se04:
   1333  1.2.22.1  thorpej 	btst	#3,%d0			| bit 3 set => CA1 on
   1334       1.1   scottr 	bne	se05
   1335  1.2.22.1  thorpej 	tstb	%a0@(ph1L)
   1336       1.1   scottr se05:
   1337       1.1   scottr 	rts
   1338       1.1   scottr 
   1339       1.1   scottr 
   1340       1.1   scottr 
   1341       1.1   scottr /*
   1342       1.1   scottr  * dstatus -- check drive status (bit 7 - N flag) wrt. a previously
   1343       1.1   scottr  * set status tag.
   1344       1.1   scottr  *
   1345  1.2.22.1  thorpej  * Parameters:	%d0	register selector
   1346  1.2.22.1  thorpej  *		%a0	IWM base address
   1347  1.2.22.1  thorpej  * Returns:	%d0	status
   1348       1.1   scottr  */
   1349       1.1   scottr dstatus:
   1350  1.2.22.1  thorpej 	tstb	%a0@(q6H)
   1351  1.2.22.1  thorpej 	moveb	%a0@(q7L),%d0
   1352  1.2.22.1  thorpej 	tstb	%a0@(q6L)		| leave in "read data reg"
   1353  1.2.22.1  thorpej 	tstb	%d0			| state for safety
   1354       1.1   scottr 	rts
   1355       1.1   scottr 
   1356       1.1   scottr 
   1357       1.1   scottr /*
   1358       1.1   scottr  * driveStat -- query drive status.
   1359       1.1   scottr  *
   1360  1.2.22.1  thorpej  * Parameters:	%a0	IWMBase
   1361  1.2.22.1  thorpej  *		%a1	VIABase
   1362  1.2.22.1  thorpej  *		%d0	register selector
   1363  1.2.22.1  thorpej  * Returns:	%d0	status (Bit 7)
   1364       1.1   scottr  */
   1365       1.1   scottr driveStat:
   1366  1.2.22.1  thorpej 	tstb	%a0@(mtrOn)		| ENABLE; turn drive on
   1367       1.1   scottr 	bsr	selDriveReg
   1368       1.1   scottr 	bsr	dstatus
   1369       1.1   scottr 	rts
   1370       1.1   scottr 
   1371       1.1   scottr 
   1372       1.1   scottr /*
   1373       1.1   scottr  * dtrigger -- toggle LSTRB line to give drive a strobe signal
   1374       1.1   scottr  * IM III says pulse length = 1 us < t < 1 ms
   1375       1.1   scottr  *
   1376  1.2.22.1  thorpej  * Parameters:	%a0	IWMBase
   1377  1.2.22.1  thorpej  *		%a1	VIABase
   1378       1.1   scottr  * Returns:	-
   1379       1.1   scottr  */
   1380       1.1   scottr dtrigger:
   1381  1.2.22.1  thorpej 	tstb	%a0@(ph3H)		| LSTRB high
   1382  1.2.22.1  thorpej 	moveb	%a1@(vBufA),%a1@(vBufA)	| intelligent nop seen in q700 ROM
   1383  1.2.22.1  thorpej 	tstb	%a0@(ph3L)		| LSTRB low
   1384       1.1   scottr 	rts
   1385       1.1   scottr 
   1386       1.1   scottr 
   1387       1.1   scottr /*
   1388       1.1   scottr  * driveCmd -- send command to drive.
   1389       1.1   scottr  *
   1390  1.2.22.1  thorpej  * Parameters:	%a0	IWMBase
   1391  1.2.22.1  thorpej  *		%a1	VIABase
   1392  1.2.22.1  thorpej  *		%d0	Command token
   1393       1.1   scottr  * Returns:	-
   1394       1.1   scottr  */
   1395       1.1   scottr driveCmd:
   1396       1.1   scottr 	bsr	selDriveReg
   1397       1.1   scottr 	bsr	dtrigger
   1398       1.1   scottr 	rts
   1399       1.1   scottr 
   1400       1.1   scottr 
   1401       1.1   scottr /*
   1402       1.1   scottr  * readSectHdr -- read and decode the next available sector header.
   1403       1.1   scottr  *
   1404       1.1   scottr  * TODO:	Poll SCC as long as interrupts are disabled.
   1405       1.1   scottr  *
   1406  1.2.22.1  thorpej  * Parameters:	%a4	sectorHdr_t address
   1407  1.2.22.1  thorpej  * Returns:	%d0	result code
   1408  1.2.22.1  thorpej  * Uses:	%d0-%d4, %a0, %a2-%a4
   1409       1.1   scottr  */
   1410       1.1   scottr readSectHdr:
   1411  1.2.22.1  thorpej 	moveq	#3,%d4			| Read 3 chars from IWM for sync
   1412  1.2.22.1  thorpej 	movew	#600,%d3		| Retries to sync to disk
   1413  1.2.22.1  thorpej 	moveq	#0,%d2			| Clear scratch regs
   1414  1.2.22.1  thorpej 	moveq	#0,%d1
   1415  1.2.22.1  thorpej 	moveq	#0,%d0
   1416  1.2.22.1  thorpej  	movel	_C_LABEL(IWMBase),%a0	| IWM base address
   1417       1.1   scottr 
   1418  1.2.22.1  thorpej 	tstb	%a0@(q7L)
   1419  1.2.22.1  thorpej 	lea	%a0@(q6L),%a0		| IWM data register
   1420       1.1   scottr shReadSy:
   1421  1.2.22.1  thorpej 	moveb	%a0@,%d2		| Read char
   1422  1.2.22.1  thorpej 	dbra	%d3,shSeekSync
   1423       1.1   scottr 
   1424  1.2.22.1  thorpej 	moveq	#noNybErr,%d0		| Disk is blank?
   1425       1.1   scottr 	bra	shDone
   1426       1.1   scottr 
   1427       1.1   scottr shSeekSync:
   1428       1.1   scottr 	bpl	shReadSy		| No char at IWM, repeat read
   1429  1.2.22.1  thorpej 	subqw	#1,%d4
   1430       1.1   scottr 	bne	shReadSy
   1431       1.1   scottr 	/*
   1432       1.1   scottr 	 * When we get here, the IWM should be in sync with the data
   1433       1.1   scottr 	 * stream from disk.
   1434       1.1   scottr 	 * Next look for sector header lead-in 'D5 AA 96'
   1435       1.1   scottr 	 */
   1436  1.2.22.1  thorpej 	movew	#1500,%d3		| Retries to seek header
   1437       1.1   scottr shLeadIn:
   1438  1.2.22.1  thorpej 	lea	hdrLeadIn,%a3		| Sector header lead-in bytes
   1439  1.2.22.1  thorpej 	moveq	#0x03,%d4		| is 3 bytes long
   1440       1.1   scottr shLI1:
   1441  1.2.22.1  thorpej 	moveb	%a0@,%d2		| Get next byte
   1442       1.2   scottr 	bpl	shLI1			| No char at IWM, repeat read
   1443  1.2.22.1  thorpej 	dbra	%d3,shLI2
   1444  1.2.22.1  thorpej 	moveq	#noAdrMkErr,%d0		| Can't find an address mark
   1445       1.1   scottr 	bra	shDone
   1446       1.1   scottr 
   1447       1.1   scottr shLI2:
   1448  1.2.22.1  thorpej 	cmpb	%a3@+,%d2
   1449       1.1   scottr 	bne	shLeadIn		| If ne restart scan
   1450  1.2.22.1  thorpej 	subqw	#1,%d4
   1451       1.1   scottr 	bne	shLI1
   1452       1.1   scottr 	/*
   1453       1.1   scottr 	 * We have found the lead-in. Now get the header information.
   1454  1.2.22.1  thorpej 	 * Reg %d4 holds the checksum.
   1455       1.1   scottr 	 */
   1456  1.2.22.1  thorpej 	lea	diskTo-0x90,%a2		| Translate disk bytes -> 6&2
   1457       1.1   scottr shHdr1:
   1458  1.2.22.1  thorpej 	moveb	%a0@,%d0		| Get 1st char
   1459       1.1   scottr 	bpl	shHdr1
   1460  1.2.22.1  thorpej 	moveb	%a2@(0,%d0),%d1		| and remap it
   1461  1.2.22.1  thorpej 	moveb	%d1,%d4
   1462  1.2.22.1  thorpej 	rorw	#6,%d1			| separate 2:6, drop hi bits
   1463       1.1   scottr shHdr2:
   1464  1.2.22.1  thorpej 	moveb	%a0@,%d0		| Get 2nd char
   1465       1.1   scottr 	bpl	shHdr2
   1466  1.2.22.1  thorpej 	moveb	%a2@(0,%d0),%d2		| and remap it
   1467  1.2.22.1  thorpej 	eorb	%d2,%d4
   1468       1.1   scottr shHdr3:
   1469  1.2.22.1  thorpej 	moveb	%a0@,%d0		| Get 3rd char
   1470       1.1   scottr 	bpl	shHdr3
   1471  1.2.22.1  thorpej 	moveb	%a2@(0,%d0),%d1		| and remap it
   1472  1.2.22.1  thorpej 	eorb	%d1,%d4
   1473  1.2.22.1  thorpej 	rolw	#6,%d1			|
   1474       1.1   scottr shHdr4:
   1475  1.2.22.1  thorpej 	moveb	%a0@,%d0		| Get 4th char
   1476       1.1   scottr 	bpl	shHdr4
   1477  1.2.22.1  thorpej 	moveb	%a2@(0,%d0),%d3		| and remap it
   1478  1.2.22.1  thorpej 	eorb	%d3,%d4
   1479       1.1   scottr shHdr5:
   1480  1.2.22.1  thorpej 	moveb	%a0@,%d0		| Get checksum byte
   1481       1.1   scottr 	bpl	shHdr5
   1482  1.2.22.1  thorpej 	moveb	%a2@(0,%d0),%d5		| and remap it
   1483  1.2.22.1  thorpej 	eorb	%d5,%d4
   1484       1.1   scottr 	bne	shCsErr			| Checksum ok?
   1485       1.1   scottr 	/*
   1486       1.1   scottr 	 * We now have in
   1487  1.2.22.1  thorpej 	 * %d1/lsb	track number
   1488  1.2.22.1  thorpej 	 * %d1/msb	bit 3 is side bit
   1489  1.2.22.1  thorpej 	 * %d2		sector number
   1490  1.2.22.1  thorpej 	 * %d3		???
   1491  1.2.22.1  thorpej 	 * %d5		checksum (=0)
   1492       1.1   scottr 	 *
   1493       1.1   scottr 	 * Next check for lead-out.
   1494       1.1   scottr 	 */
   1495  1.2.22.1  thorpej 	moveq	#1,%d4			| is 2 bytes long
   1496       1.1   scottr shHdr6:
   1497  1.2.22.1  thorpej 	moveb	%a0@,%d0		| Get token
   1498       1.1   scottr 	bpl	shHdr6
   1499  1.2.22.1  thorpej 	cmpb	%a3@+,%d0		| Check
   1500       1.1   scottr 	bne	shLOErr			| Fault!
   1501  1.2.22.1  thorpej 	dbra	%d4,shHdr6
   1502  1.2.22.1  thorpej 	movew	%d1,%d0			| Isolate side bit
   1503  1.2.22.1  thorpej 	lsrw	#8,%d0
   1504  1.2.22.1  thorpej 	moveb	%d0,%a4@+		| and store it
   1505  1.2.22.1  thorpej 	moveb	%d1,%a4@+		| Store track number
   1506  1.2.22.1  thorpej 	moveb	%d2,%a4@+		| and sector number
   1507  1.2.22.1  thorpej 	moveq	#0,%d0			| All is well
   1508       1.1   scottr 	bra	shDone
   1509       1.1   scottr 
   1510       1.1   scottr shCsErr:
   1511  1.2.22.1  thorpej 	moveq	#badCkSmErr,%d0		| Bad sector header checksum
   1512       1.1   scottr 	bra	shDone
   1513       1.1   scottr shLOErr:
   1514  1.2.22.1  thorpej 	moveq	#badBtSlpErr,%d0	| Bad address mark (no lead-out)
   1515       1.1   scottr 
   1516       1.1   scottr shDone:
   1517  1.2.22.1  thorpej 	tstl	%d0			| Set flags
   1518       1.1   scottr 	rts
   1519