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