|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /**
26: * Copyright (c) 1994-1996 NeXT Software, Inc. All rights reserved.
27: * Copyright 1993-1995 by Apple Computer, Inc., all rights reserved.
28: * Copyright 1997 Apple Computer Inc. All Rights Reserved.
29: * @author Martin Minow mailto:[email protected]
30: * @revision 1997.02.13 Initial conversion from AMDPCSCSIDriver sources.
31: * Accessor functions for the 53C96 registers and commands.
32: * As noted above, the class provides an instance variable defined as:
33: * volatile UInt8 *gSCSILogicalAddress The chip's LogicalAddress
34: *
35: * Set tabs every 4 characters.
36: * Edit History
37: * 1997.02.13 MM Initial conversion from AMDPCSCSIDriver sources.
38: * 1997.07.18 MM Added USE_CURIO_METHODS and wrote macros for the
39: * one-liner methods.
40: */
41:
42: #import "Apple96CurioPrivate.h"
43: #import "Apple96CurioPublic.h"
44: #import "Apple96CurioDBDMA.h"
45: #import "MacSCSICommand.h"
46: #import <driverkit/generalFuncs.h>
47: #import <kernserv/prototypes.h>
48:
49: extern IONamedValue gAutomatonStateValues[];
50:
51: @implementation Apple96_SCSI(Curio)
52:
53: /*
54: * This spin-loop looks for another chip operation - it prevents
55: * exiting the interrupt service routine if the chip presents
56: * another operation within ten microseconds. Note that this
57: * must be called from an IOThread, not from a "real" primary
58: * interrupt service routine.
59: */
60: - (Boolean) curioQuickCheckForChipInterrupt
61: {
62: ns_time_t startTime;
63: ns_time_t endTime;
64: unsigned elapsedNSec;
65: Boolean result;
66:
67: ENTRY("Cin curioQuickCheckForChipInterrupt");
68: IOGetTimestamp(&startTime);
69: result = FALSE;
70: do {
71: if (CURIOinterruptPending()) {
72: result = TRUE;
73: break;
74: }
75: IOGetTimestamp(&endTime);
76: elapsedNSec = (unsigned) (endTime - startTime);
77: } while (elapsedNSec < 10000U);
78: RESULT(result);
79: return (result);
80: }
81:
82: /*
83: * Determine if SCSI interrupt is pending. If so, store the current
84: * chip state. Note that reading the interrupt register clears the
85: * interrupt source, so this should be done once for each interrupt.
86: */
87: - (Boolean) curioInterruptPending
88: {
89: UInt8 chipStatus;
90: Boolean result = FALSE;
91:
92:
93: ENTRY( "Cip curioInterruptPending" );
94:
95: /* mlj - use WHILE to check for double interrupts */
96: /* and get get most recent conditions. */
97: while (((chipStatus = CURIOreadStatusRegister()) & sIntPend) != 0)
98: {
99: result = TRUE;
100: gSaveStatus = chipStatus;
101: gSaveSeqStep = CURIOreadSequenceStateRegister();
102: gSaveInterrupt = CURIOreadInterruptRegister();
103: }
104: RESULT( result );
105: return result;
106: }/* end curioInterruptPending */
107:
108:
109: /*
110: * Store the current command into the fifo. If this is an autosense,
111: * store a REQUEST SENSE command.
112: */
113: - (void) curioPutCommandIntoFifo
114: {
115: IOSCSIRequest *scsiReq;
116: UInt32 i;
117:
118: ENTRY("Cpc curioPutCommandIntoFifo");
119: ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
120: scsiReq = gActiveCommand->scsiReq;
121: if (gActiveCommand->flagIsAutosense) {
122: UInt32 actualAutosenseTransferLength;
123: /*
124: * This should be provided by the client (and checked that it is
125: * less than or equal to kMaxAutosenseByteCount). Note that this
126: * sequence is duplicated in Apple96HWPrivate.m.
127: */
128: actualAutosenseTransferLength = (sizeof (esense_reply_t) < kMaxAutosenseByteCount)
129: ? (sizeof (esense_reply_t)) : kMaxAutosenseByteCount;
130: ASSERT(actualAutosenseTransferLength <= 255);
131: /*
132: * Put the autosense command into the fifo.
133: */
134: CURIOputByteIntoFifo(kScsiCmdRequestSense);
135: CURIOputByteIntoFifo(scsiReq->lun << 5);
136: CURIOputByteIntoFifo(0);
137: CURIOputByteIntoFifo(0);
138: CURIOputByteIntoFifo(actualAutosenseTransferLength);
139: CURIOputByteIntoFifo(0);
140: }
141: else {
142: /*
143: * Put the original command into the fifo.
144: */
145: for (i = 0; i < gActiveCommand->cdbLength; i++) {
146: CURIOputByteIntoFifo(((UInt8 *) &scsiReq->cdb)[i]);
147: }
148: }
149: EXIT();
150: }
151:
152: /*
153: * Reset the chip to hardware power on state.
154: */
155: - (void) curioResetChip
156: {
157: ENTRY("Crc curioResetChip");
158: CURIOsetCommandRegister(cRstSChp); /* Reset chip */
159: IODelay(50); /* Chip settle */
160: CURIOnop(); /* Re-enable chip */
161: CURIOflushFifo(); /* In a clean state */
162: EXIT();
163: }
164:
165: /**
166: * The caller (hardwareReset and the bus reset interrupt handler) must delay for 250 msec
167: * after resetting the bus or detecting a bus reset. This serves two purposes: "The 53C96
168: * needs a vacation of about 100 msec after a reset otherwise it gets cranky" -- according
169: * to notes in HALc96.c. Also, some devices don't respond if we issue another command too
170: * quickly after bus reset.
171: */
172: - (void) curioResetSCSIBus
173: {
174: ENTRY("Crb curioResetSCSIBus");
175: SynchronizeIO();
176: CURIOsetCommandRegister(cRstSBus);
177: EXIT();
178: }
179:
180: #if USE_CURIO_METHODS
181: /*
182: * These are stub methods that implement the exact same code as
183: * the inline macros.
184: */
185:
186: /**
187: * Retrieve the status register. This can be done without disturbing
188: * the chip operation state.
189: */
190: - (UInt8) curioReadStatusRegister
191: {
192: return (__CURIOreadStatusRegister());
193: }
194:
195: /**
196: * Retrieve the internal state register. This is done after an interrupt.
197: */
198: - (UInt8) curioReadSequenceStateRegister
199: {
200: return (__CURIOreadSequenceStateRegister());
201: }
202:
203: /**
204: * Retrieve the interrupt register. This is done after an interrupt.
205: * Note: reading this register "releases" the chip. Registers must
206: * be read in the following order:
207: * 1. Status (skip the rest if the interrupt bit is clear)
208: * 2. SequenceStep
209: * 3. Interrupt
210: */
211: - (UInt8) curioReadInterruptRegister
212: {
213: return (__CURIOreadInterruptRegister());
214: }
215:
216: /**
217: * The target is in MSGI phase. Start the transfer.
218: */
219: - (void) curioStartMSGIAction
220: {
221: __CURIOstartMSGIAction();
222: }
223:
224: /**
225: * CurioNop is a temporizing command to give the chip time to stabalize
226: * its internal registers.
227: */
228: - (void) curioNop
229: {
230: __CURIOnop(); /* Restart the chip */
231: }
232:
233: /**
234: * Start a byte-by-byte transfer that does not involve the DMA subsystem.
235: */
236: - (void) curioStartNonDMATransfer
237: {
238: __CURIOstartNonDMATransfer(); /* Start a non-DMA transfer */
239: }
240:
241: /**
242: * Start a DMA transfer.
243: */
244: - (void) curioStartDMATransfer
245: : (UInt32) transferCount
246: {
247: ENTRY("Cds curioStartDMATransfer");
248: __CURIOstartDMATransfer(transferCount);
249: EXIT();
250: }
251:
252: - (void) curioTransferPad
253: : (Boolean) forOutput
254: {
255: __CURIOtransferPad(forOutput);
256: }
257:
258: /**
259: * CurioClearTransferCountZeroBit
260: * This is called after DMA transfers to stabalize the DMA and clear its fifo.
261: * It is needed to keep the process alive in the following sequence:
262: * DATO Start DMA transfer to the target
263: * MSGI Target changes to message in in order to disconnect.
264: */
265: - (void) curioClearTransferCountZeroBit
266: {
267: __CURIOclearTransferCountZeroBit(); /* Clear TC zero bit */
268: }
269:
270: /**
271: * Return the current transfer count. This is generally zero after DMA, but will be
272: * non-zero if some data was not transferred.
273: */
274: - (UInt32) curioGetTransferCount
275: {
276: UInt32 result;
277:
278: ENTRY("Cgt curioGetTransferCount");
279: result = __CURIOgetTransferCount();
280: RESULT(result);
281: return (result);
282: }
283:
284: /**
285: * Load the target destination id register.
286: */
287: - (void) curioSetDestinationID
288: : (UInt8) targetID
289: {
290: __CURIOsetDestinationID(targetID);
291: }
292:
293: /**
294: * Start an initiator-initiated command-complete sequence.
295: */
296: - (void) curioInitiatorCommandComplete
297: {
298: __CURIOinitiatorCommandComplete();
299: }
300:
301: /**
302: * The bus is (presumably) free: allow us to be reselected.
303: */
304: - (void) curioEnableSelectionOrReselection
305: {
306: __CURIOenableSelectionOrReselection();
307: }
308:
309: /**
310: * Disconnect from the SCSI bus.
311: */
312: - (void) curioDisconnect
313: {
314: __CURIOdisconnect();
315: }
316:
317:
318: /**
319: * Manipulate the FIFO
320: * CurioGetFifoByte Return the current fifo byte.
321: * CurioPutByteIntoFifo Store a byte into the fifo
322: * CurioFlushFifo Clear the fifo
323: * CurioGetFifoCount Get the number of bytes in the fifo.
324: * Note: the fifo only holds 16 bytes. For some reason,
325: * we ignore the 0x10 bit (follows Copland DR1 debugging).
326: */
327: - (UInt8) curioGetFifoByte
328: {
329: return (__CURIOgetFifoByte());
330: }
331:
332: - (void) curioPutByteIntoFifo
333: : (UInt8) theByte
334: {
335: __CURIOputByteIntoFifo(theByte);
336: }
337:
338: - (void) curioFlushFifo
339: {
340: __CURIOflushFifo();
341: }
342:
343: - (UInt32) curioGetFifoCount
344: {
345: return (__CURIOgetFifoCount());
346: }
347:
348: /**
349: * Configure the 53C96 chip.
350: */
351: - (void) curioSetSelectionTimeout
352: : (UInt8) selectionTimeout
353: {
354: __CURIOsetSelectionTimeout(selectionTimeout);
355: }
356:
357: - (void) curioConfigForNonDMA
358: {
359: __CURIOconfigForNonDMA();
360: }
361:
362: - (void) curioConfigForDMA
363: {
364: __CURIOconfigForDMA();
365: }
366:
367: /**
368: * Manage Message Phase
369: */
370: - (void) curioMessageAccept
371: {
372: __CURIOmessageAccept();
373: }
374:
375: - (void) curioMessageReject
376: {
377: __CURIOmessageReject();
378: }
379:
380: - (void) curioSetATN
381: {
382: __CURIOsetATN();
383: }
384:
385: - (void) curioClearATN
386: {
387: __CURIOclearATN();
388: }
389:
390:
391: /*
392: * Sync negotiation methods
393: * To do: don't load a register if its shadow has the same value..
394: */
395: - (void) curioSetSynchronousOffset
396: : (UInt8) synchronousOffset
397: {
398: __CURIOsetSynchronousOffset(synchronousOffset);
399: }
400:
401: - (void) curioSetSynchronousPeriod
402: : (UInt8) synchronousPeriod
403: {
404: __CURIOsetSynchronousPeriod(synchronousPeriod);
405: }
406:
407: /**
408: * Write a random register (used for configuration registers)
409: */
410: - (void) curioWriteRegister
411: : (UInt8) curioRegister
412: value : (UInt8) value
413: {
414: __CURIOwriteRegister(curioRegister, value);
415: }
416:
417: /**
418: * Read a random register (used for configuration registers)
419: */
420: - (UInt8) curioReadRegister
421: : (UInt8) curioRegister
422: {
423: return (__CURIOreadRegister(curioRegister));
424: }
425:
426: /**
427: * This is the only place that the command register is written.
428: */
429: - (void) curioSetCommandRegister
430: : (UInt8) commandByte
431: {
432: __CURIOsetCommandRegister(commandByte);
433: }
434:
435: /**
436: * Error recovery needs to peek at the last command
437: */
438: - (UInt8) curioReadCommandRegister
439: {
440: return (__CURIOreadCommandRegister());
441: }
442:
443: /*
444: * Convert the selection timeout to the value that must be stored in the
445: * chip registers.
446: */
447: - (UInt32) curioSelectTimeout
448: : (UInt32) selectTimeoutMSec
449: curioClockMHz : (UInt32) chipClockRateMHz
450: curioClockFactor : (UInt32) chipClockFactor
451: {
452: return (
453: __CURIOsetSelectTimeout(
454: selectTimeoutMSec,
455: chipClockRateMHz,
456: chipClockFactor)
457: );
458: }
459: #endif /* USE_CURIO_METHODS */
460:
461: @end /* Apple96_SCSI(Curio) */
462:
463: #if USE_CURIO_METHODS || WRITE_CHIP_OPERATION_INTO_TIMESTAMP_LOG
464: volatile UInt8
465: __CurioReadRegister__(
466: volatile UInt8 *scsiLogicalAddress,
467: UInt32 index
468: )
469: {
470: volatile UInt8 result = scsiLogicalAddress[index];
471: const char *why;
472: const char *what;
473: switch (index) {
474: case rXCL: what = "XCL"; break;
475: case rXCM: what = "XCM"; break;
476: case rFFO: what = "FFO"; break;
477: case rCMD: what = "CMD"; break;
478: case rSTA: what = "STA"; break;
479: case rINT: what = "INT"; break;
480: case rSQS: what = "SQS"; break;
481: case rFOS: what = "FOS"; break;
482: case rCF1: what = "CF1"; break;
483: case rCKF: what = "CKF"; break;
484: case rTST: what = "TST"; break;
485: case rCF2: what = "CF2"; break;
486: case rCF3: what = "CF3"; break;
487: case rCF4: what = "CF4"; break;
488: case rTCH: what = "TCH"; break;
489: case rDMA: what = "DMA"; break;
490: default: what = "?\?\?"; break;
491: }
492: RAW_TAG(OSTag('<', what), (index << 8) | result);
493: return (result);
494: }
495:
496: void
497: __CurioWriteRegister__(
498: volatile UInt8 *scsiLogicalAddress,
499: UInt32 index,
500: UInt8 value
501: )
502: {
503: const char *what;
504: switch (index) {
505: case rXCL: what = "XCL"; break;
506: case rXCM: what = "XCM"; break;
507: case rFFO: what = "FFO"; break;
508: case rCMD: what = "CMD"; break;
509: case rSTA: what = "DST"; break;
510: case rINT: what = "TMO"; break;
511: case rSQS: what = "SQS"; break;
512: case rFOS: what = "FOS"; break;
513: case rCF1: what = "CF1"; break;
514: case rCKF: what = "CKF"; break;
515: case rTST: what = "TST"; break;
516: case rCF2: what = "CF2"; break;
517: case rCF3: what = "CF3"; break;
518: case rCF4: what = "CF4"; break;
519: case rTCH: what = "TCH"; break;
520: case rDMA: what = "DMA"; break;
521: default: what = "?\?\?"; break;
522: }
523: RAW_TAG(OSTag('>', what), (index << 8) | value);
524: scsiLogicalAddress[index] = value;
525: }
526: #endif /* USE_CURIO_METHODS */
527:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.