|
|
1.1 root 1: {\rtf0\ansi{\fonttbl\f2\fmodern Courier;\f1\fmodern Ohlfs;}
2: \paperw13040
3: \paperh8220
4: \margl20
5: \margr120
6: {\colortbl;\red0\green0\blue0;}
7: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\f2\b\i0\ulnone\fs28\fc1\cf1 AMD 53C974/79C974 SCSI Driver Design Notes\
8:
9: \f1\b0\fs24\fc0\cf0 \
10: \
11:
12: \pard\tx720\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\f2\b\fs28\fc0\cf0 1. General\
13:
14: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0\cf0 \
15:
16: \f1\b0\fs24\li720\fc1\cf1 This driver is primarily intended to be used with the AMD 79C974 PCnet-SCSI combo chip, which combines an Ethernet Controller, a SCSI Host Adapter, and a PCI Bus Interface module on one chip. This driver only controls the SCSI logic on the 79C974; a separate driver is used for the Ethernet logic. The driver also should work with the AMD 53C974, a subset of the 79C974. (This has not been tested as of 25 Jan, 1995.) The 53C974 is, in turn, a superset of the old NCR 53C90A chip, which was the SCSI controller used on all NeXT ("Black") hardware.\
17: \
18: This driver implements the following features:\
19: \
20: � Disconnect/Reselect\
21: � 10 MB/s "Fast SCSI" Synchronous Transfers\
22: � SCSI-2 Command Queueing \
23: � Auto Request Sense\
24: \
25: Synchronous Mode, Command Queueing, and Fast SCSI can be disabled and enabled for the driver as a whole via the driver instance's Instance table. There is a Custom Device Inspector used by the Configure App which allows the user to specify these parameters. Per-target disable flags for Command Queueing and Synchronous Mode are also kept for both of the features, so that if a target rejects an attempt to use the mode (typically via a "Message Reject" message), no further attempts will be made to use the feature with that target. Synchronous Transfer offset and period are also negotiated and kept on a per-target basis, per the SCSI-2 specification. \
26: \
27: \
28:
29: \pard\tx720\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\f2\b\fs28\fc0\cf0 2. Architecture\
30:
31: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0\cf0 \
32:
33: \f1\b0\fs24\li720\fc1\cf1 Unlike most other SCSI Host Adapter drivers for the Intel Platform, this driver is involved in a lot of low-level SCSI events, including dealing with phase changes, setting ATN at appropriate times, doing synchronous transfer negotiation, etc. The driver has to maintain quite a bit of state to keep track of what is occurring on the bus and typically responds to 3 or 4 interrupts for every SCSI command.\
34: \
35: The driver is implemented as a subclass of
36: \f2\b\fs28 IOSCSIController
37: \f1\b0\fs24 called
38: \f2\b\fs28 AMD_SCSI
39: \f1\b0\fs24 .
40: \f2\b\fs28 IOSCSIController
41: \f1\b0\fs24 is a subclass of
42: \f2\b\fs28 IODirectDevice
43: \f1\b0\fs24 . The
44: \f2\b\fs28 IODirectDevice
45: \f1\b0\fs24 categories
46: \f2\b\fs28 IOEISADirectDevice
47: \f1\b0\fs24 and
48: \f2\b\fs28 IOPCIDirectDevice
49: \f1\b0\fs24 are also used by
50: \f2\b\fs28 AMD_SCSI
51: \f1\b0\fs24 .\
52: \
53: \
54:
55: \f2\b\fs28\fc0\cf0 Control Flow and the I/O thread\
56:
57: \f1\b0\fs24\fc1\cf1 \
58: The control flow in the driver is the same as for all other NextStep SCSI drivers - all access to the hardware is done by one thread, the I/O thread. This eliminates the need for locks around accesses to the hardware and other critical resources. All communication with the I/O thread by exported methods is performed by passing a command struct, called a
59: \f2\b\fs28 commandBuf
60: \f1\b0\fs24 , to the I/O thread via the instance variable
61: \f2\b\fs28 commandQ
62: \f1\b0\fs24 .
63: \f2\b\fs28 CommandQ
64: \f1\b0\fs24 is protected by
65: \f2\b\fs28 commandLock
66: \f1\b0\fs24 . After enqueueing a
67: \f2\b\fs28 commandBuf
68: \f1\b0\fs24 on
69: \f2\b\fs28 commandQ
70: \f1\b0\fs24 , a message with a
71: \f2\b\fs28 msg_id
72: \f1\b0\fs24 of
73: \f2\b\fs28 IO_COMMAND_MSG
74: \f1\b0\fs24 is sent to the driver's interrupt port. The I/O thread is the only code which does a
75: \f2\b\fs28 msg_receive()
76: \f1\b0\fs24 on the interrupt port. Subsequent to initialization,
77: \f2\b\fs28 commandQ
78: \f1\b0\fs24 and
79: \f2\b\fs28 commandLock
80: \f1\b0\fs24 are the only data shared by exported methods and the I/O thread.\
81: \
82: I/O complete notification is performed via
83: \f2\b\fs28 commandBuf.cmdLock
84: \f1\b0\fs24 , which is an
85: \f2\b\fs28 NXConditionLock
86: \f1\b0\fs24 . Exported methods wait on this lock after passing a
87: \f2\b\fs28 commandBuf
88: \f1\b0\fs24 to the I/O thread. \
89: \
90: Subsequent to initialization, the only methods in the driver which do
91: \f2\b\i\fs28 not
92: \f1\b0\i0\fs24 run solely as part of the I/O thread are:\
93: \
94:
95: \f2\b\fs28 -executeRequest:buffer:client:\
96: -resetSCSIBus\
97: -resetStats\
98: -numQueueSamples\
99: -sumQueueLengths\
100: -maxQueueLength\
101: -executeCmdBuf\
102:
103: \f1\b0\fs24 \
104: These are all found in
105: \f2\b\fs28 AMD_SCSI.m
106: \f1\b0\fs24 . (Note: unless otherwise indicated, all files referred to in this document reside in the AMD53C974SCSIDriver_reloc.tproj directory of the driver project.) The first two methods are exported methods used for normal SCSI I/O and are called by indirect SCSI devices like SCSIDisk and SCSITape. The next four are associated with gathering statistics and are called from IOSCSIController. The last one,
107: \f2\b\fs28 -executeCmdBuf
108: \f1\b0\fs24 , is the common means by which
109: \f2\b\fs28 -executeRequest:buffer:client:
110: \f1\b0\fs24 and
111: \f2\b\fs28 -resetSCSIBus
112: \f1\b0\fs24 pass
113: \f2\b\fs28 commandBuf
114: \f1\b0\fs24 s to the I/O thread and wait for completion.\
115: \
116: \
117:
118: \f2\b\fs28\fc0\cf0 Processing of commands by the I/O thread\
119: \
120:
121: \f1\b0\fs24\fc1\cf1 The I/O thread's job is basically to dequeue commands from
122: \f2\b\fs28 commandQ
123: \f1\b0\fs24 , start up SCSI transactions on the 79C974, and deal with interrupts. All of the
124: \f2\b\fs28 msg_receive()
125: \f1\b0\fs24 s which fetch command requests and interrupt events from the driver's interrupt port are done by
126: \f2\b\fs28 IODirectDevice
127: \f1\b0\fs24 's I/O Thread. If a command message is received,
128: \f2\b\fs28 IODirectDevice
129: \f1\b0\fs24 calls
130: \f2\b\fs28 -commandRequestOccurred
131: \f1\b0\fs24 . If an interrupt message is received,
132: \f2\b\fs28 -interruptOccurred
133: \f1\b0\fs24 is called. Both of these methods are implemented by the
134: \f2\b\fs28 AMD_SCSI
135: \f1\b0\fs24 class. \
136: \
137: When an exported method passes a
138: \f2\b\fs28 commandBuf
139: \f1\b0\fs24 to the I/O thread, it is quite possible that the I/O thread can not immediately process the command due to the fact that there is already a command active on the SCSI bus at that time. If this occurs, the incoming command is enqueued on
140: \f2\b\fs28 pendingQ
141: \f1\b0\fs24 . (Note that the decision as to whether a command can be processed, and the act of enqueueing a command on
142: \f2\b\fs28 pendingQ
143: \f1\b0\fs24 , are solely the responsibility of the I/O thread. There are no races or deadlock conditions here.) Whenever the I/O thread detects a "Bus Free" condition, it will look at
144: \f2\b\fs28 pendingQ
145: \f1\b0\fs24 , and if the queue is non-empty, the first
146: \f2\b\fs28 commandBuf
147: \f1\b0\fs24 in the queue is dequeued and used to start up a new SCSI transaction. \
148: \
149: The
150: \f2\b\fs28 commandBuf
151: \f1\b0\fs24 associated with the currently active SCSI transaction is always kept in
152: \f2\b\fs28 activeCmd
153: \f1\b0\fs24 . If
154: \f2\b\fs28 activeCmd
155: \f1\b0\fs24 is NULL, the SCSI bus is either free, or there is a reselection in progress for which we do not have complete target/LUN/queue tag information. \
156: \
157: When an active SCSI target disconnects (as opposed to doing a "Command Complete"), the I/O thread places the associated
158: \f2\b\fs28 commandBuf
159: \f1\b0\fs24 on
160: \f2\b\fs28 disconnectQ
161: \f1\b0\fs24 . Whenever a reselection occurs,
162: \f2\b\fs28 disconnectQ
163: \f1\b0\fs24 is scanned for a commandBuf which matches the reselecting target, LUN, and (possibly) queue tag. If a match is found, the
164: \f2\b\fs28 commandBuf
165: \f1\b0\fs24 is dequeued from
166: \f2\b\fs28 disconnectQ
167: \f1\b0\fs24 and becomes
168: \f2\b\fs28 activeCmd
169: \f1\b0\fs24 .\
170: \
171: The driver contains logic to prevent sending a command to a target/LUN nexus which currently has an active, but disconnected, command - unless command queueing is enabled for the driver, and is not disabled for the given target. This allows higher layers in the system (e.g., SCSIDisk) to enqueue multiple requests for one target and LUN without worrying about the nexus's current state. This logic uses the array
172: \f2\b\fs28 activeArray[][]
173: \f1\b0\fs24 , which is an array of counters which keep track of how many I/Os are active on a per-LUN basis. When command queueing is disabled (either globally, or on a per-target basis), an
174: \f2\b\fs28 activeArray
175: \f1\b0\fs24 counter has a maximum value of 1. If command queueing is enabled, an
176: \f2\b\fs28 activeArray
177: \f1\b0\fs24 counter has a maximum value of the target's queue length (if known). See the
178: \f2\b\fs28 -cmdBufOk:
179: \f1\b0\fs24 method, in AMD_SCSI.m, for the implementation of the decision as to whether a target/lun nexus is ready to accept a new command.\
180: \
181: \
182:
183: \pard\tx720\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\f2\b\fs28\fc0\cf0 3. Organization\
184:
185: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0\cf0 \
186:
187: \f1\b0\fs24\li720\fc1\cf1 The driver was organized to facilitate porting to other platforms using chips similar to the 79C974, and also to other "dumb" host adapter chips on the x86 platform. With some exceptions, all of the logic which is independent of either the chip or the host bus is contained in
188: \f2\b\fs28 AMD_SCSI.m
189: \f1\b0\fs24 . All of the logic which deals directly with the 79C974 is contained in
190: \f2\b\fs28 AMD_Chip.m
191: \f1\b0\fs24 and
192: \f2\b\fs28 AMD_ChipPrivate.m.
193: \f1\b0\fs24 All of the logic which is specific to the x86 architecture and the PCI bus is contained in
194: \f2\b\fs28 AMD_x86.m
195: \f1\b0\fs24 . The API to
196: \f2\b\fs28 AMD_Chip.m
197: \f1\b0\fs24 which is public to the other parts of the driver consists of six methods:\
198: \
199: �
200: \f2\b\fs28 -probeChip
201: \f1\b0\fs24 , performs one-time-only initialization.\
202: �
203: \f2\b\fs28 -hwReset
204: \f1\b0\fs24 , reusable chip reset/init.\
205: �
206: \f2\b\fs28 -scsiReset
207: \f1\b0\fs24 , performs SCSI reset.\
208: �
209: \f2\b\fs28 -hwStart:
210: \f1\b0\fs24 , starts up a new SCSI transaction.\
211: �
212: \f2\b\fs28 -hwInterrupt
213: \f1\b0\fs24 , deals with an interrupt event.\
214: �
215: \f2\b\fs28 -logRegs
216: \f1\b0\fs24 , a debugging function to dump registers to the console.\
217:
218: \f2\b\fs28\fc0\cf0 \
219:
220: \f1\b0\fs24\fc1\cf1 When porting this driver to a new chip, these six methods are pretty much all that need to be re-implemented (in addition to any private, implementation-specific methods needed for the new chip). \
221: \
222: The design goal of separating out the chip-specific, architecture-specific, and hardware-independent functionality into separate modules was not religiously adhered to. Sometimes, for example in the routines to handle DMA in
223: \f2\b\fs28 AMD_x86.m
224: \f1\b0\fs24 , there is a mixture of chip- and bus-specific functions in one file (or even one method). The tradeoff between design clarity and portability went towards design clarity in these cases.\
225: \
226: \
227:
228: \pard\tx720\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\f2\b\fs28\fc0\cf0 4. File contents\
229:
230: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0\cf0 \
231:
232: \f1\b0\fs24\li720\fc1\cf1 The following files all exist in the AMD53C974SCSIDriver_reloc.tproj directory. (AMD53C974SCSIDriver_reloc is the driver's loadable binary.)\
233: \
234: \
235: AMD_SCSI.h\
236: \
237:
238: \fi-20\li1160 Exported interface to the driver. Typically used by SCSI indirect drivers like SCSIDisk and SCSITape.\
239: \
240:
241: \fi0\li720 AMD_Private.h\
242:
243: \li0 \
244:
245: \fi-20\li1160 Private hardware-independent methods.\
246: \
247:
248: \fi0\li720 AMD_Types.h\
249:
250: \li0 \
251:
252: \fi-20\li1160 Private structs and #defines used by the entire driver. \
253: \
254:
255: \fi0\li720 AMD_SCSI.m\
256:
257: \li0 \
258:
259: \fi-20\li1160 Implementation of AMD_SCSI.h and AMD_Private.h methods.\
260: \
261:
262: \fi0\li720 AMD_x86.[hm]\
263:
264: \li0 \
265:
266: \fi-20\li1160 Methods specific to Intel platform and PCI bus.\
267: \
268:
269: \fi0\li720 AMD_Chip.[hm]\
270:
271: \li0 \
272:
273: \fi-20\li1160 Chip-specific methods available to the rest of the driver.\
274: \
275:
276: \fi0\li720 AMD_ChipPrivate.m\
277:
278: \li0 \
279:
280: \fi-20\li1160 Chip-specific methods available only to AMD_Chip.m.\
281: \
282:
283: \fi0\li720 AMD_Regs.h\
284:
285: \li0 \
286:
287: \fi-20\li1160 Definitions of AMD 79C974 registers.\
288: \
289:
290: \fi0\li720 bringup.h\
291:
292: \li0 \
293:
294: \fi-20\li1160 Debugging and bringup flags.\
295: \
296:
297: \fi0\li720 AMD_ddm.h\
298:
299: \li0 \
300:
301: \fi-20\li1160 #defines used for DDM calls.\
302: \
303:
304: \fi0\li720 AMD.ddm\
305:
306: \li0 \
307:
308: \fi-20\li1160 Config file used by DDMViewer.\
309: \
310:
311: \fi0\li720 ioPorts.[ch]\
312:
313: \li0 \
314:
315: \fi-20\li1160 A DEBUG version of <driverkit/i386/ioPorts.h>.\
316: \
317:
318: \fi0\li720 pciConf.h\
319:
320: \li0 \
321:
322: \fi-20\li1160 #defines for PCI configuration registers.\
323: \
324:
325: \fi0\li720 configKeys.h\
326:
327: \li0 \
328:
329: \fi-20\li1160 String definition for keys in driver's config table.\
330: \
331:
332: \fi0\li720 Makefile.driver_preamble \
333: Makefile.preamble\
334: Makefile.postamble\
335:
336: \li0 \
337:
338: \fi-20\li1160 Standard Makefile additions, common to all drivers.\
339: \
340: \
341:
342: \f2\b\fs28\fi0\li720 Other Files
343: \f1\b0\fs24 \
344: \
345: Here is a brief description of the other files residing in the driver project's root directory. \
346: \
347: \
348: SCSIInspector.[mh]\
349: \
350:
351: \fi-20\li1160 Custom Device Inspector for use in the Configure App.\
352: \
353:
354: \fi0\li720 Default.table \
355: \
356:
357: \fi-20\li1160 Template used by Configure App for creating Instance tables.\
358: \
359:
360: \fi0\li720 English.lproj/AMDInspector.nib\
361: \
362:
363: \fi-20\li1160 Localizable nib file for Custom Device Inspector. \
364:
365: \fi0\li720 \
366: English.lproj/Localizable.strings\
367: \
368:
369: \fi-20\li1160 Localizable strings file used by Configure App.\
370:
371: \fi0\li720 \
372: English.lproj/DriverHelp/*\
373: \
374: Support for on-line help in the Configure App. \
375: \
376: Makefile \
377: PB.project \
378: \
379:
380: \fi-20\li1160 Created by Project Builder.\
381:
382: \fi0\li720 \
383: SGS_ENV\
384: \
385:
386: \fi-20\li1160 For NeXT internal use.\
387: \
388:
389: \fi0\li720 Makefile.postamble\
390: Makefile.preamble\
391: \
392:
393: \fi-20\li1160 Standard Makefile additions, common to all drivers.\
394:
395: \fi0\li720 \
396: changes\
397: \
398:
399: \fi-20\li1160 Revision history of this project.\
400: \
401:
402: \fi0\li720 README.rtf\
403: \
404:
405: \fi-20\li1160 This file.\
406:
407: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.