diff options
47 files changed, 3864 insertions, 291 deletions
diff --git a/Documentation/scsi/ChangeLog.arcmsr b/Documentation/scsi/ChangeLog.arcmsr new file mode 100644 index 00000000000..162c47fdf45 --- /dev/null +++ b/Documentation/scsi/ChangeLog.arcmsr | |||
@@ -0,0 +1,56 @@ | |||
1 | ************************************************************************** | ||
2 | ** History | ||
3 | ** | ||
4 | ** REV# DATE NAME DESCRIPTION | ||
5 | ** 1.00.00.00 3/31/2004 Erich Chen First release | ||
6 | ** 1.10.00.04 7/28/2004 Erich Chen modify for ioctl | ||
7 | ** 1.10.00.06 8/28/2004 Erich Chen modify for 2.6.x | ||
8 | ** 1.10.00.08 9/28/2004 Erich Chen modify for x86_64 | ||
9 | ** 1.10.00.10 10/10/2004 Erich Chen bug fix for SMP & ioctl | ||
10 | ** 1.20.00.00 11/29/2004 Erich Chen bug fix with arcmsr_bus_reset when PHY error | ||
11 | ** 1.20.00.02 12/09/2004 Erich Chen bug fix with over 2T bytes RAID Volume | ||
12 | ** 1.20.00.04 1/09/2005 Erich Chen fits for Debian linux kernel version 2.2.xx | ||
13 | ** 1.20.00.05 2/20/2005 Erich Chen cleanly as look like a Linux driver at 2.6.x | ||
14 | ** thanks for peoples kindness comment | ||
15 | ** Kornel Wieliczek | ||
16 | ** Christoph Hellwig | ||
17 | ** Adrian Bunk | ||
18 | ** Andrew Morton | ||
19 | ** Christoph Hellwig | ||
20 | ** James Bottomley | ||
21 | ** Arjan van de Ven | ||
22 | ** 1.20.00.06 3/12/2005 Erich Chen fix with arcmsr_pci_unmap_dma "unsigned long" cast, | ||
23 | ** modify PCCB POOL allocated by "dma_alloc_coherent" | ||
24 | ** (Kornel Wieliczek's comment) | ||
25 | ** 1.20.00.07 3/23/2005 Erich Chen bug fix with arcmsr_scsi_host_template_init | ||
26 | ** occur segmentation fault, | ||
27 | ** if RAID adapter does not on PCI slot | ||
28 | ** and modprobe/rmmod this driver twice. | ||
29 | ** bug fix enormous stack usage (Adrian Bunk's comment) | ||
30 | ** 1.20.00.08 6/23/2005 Erich Chen bug fix with abort command, | ||
31 | ** in case of heavy loading when sata cable | ||
32 | ** working on low quality connection | ||
33 | ** 1.20.00.09 9/12/2005 Erich Chen bug fix with abort command handling, firmware version check | ||
34 | ** and firmware update notify for hardware bug fix | ||
35 | ** 1.20.00.10 9/23/2005 Erich Chen enhance sysfs function for change driver's max tag Q number. | ||
36 | ** add DMA_64BIT_MASK for backward compatible with all 2.6.x | ||
37 | ** add some useful message for abort command | ||
38 | ** add ioctl code 'ARCMSR_IOCTL_FLUSH_ADAPTER_CACHE' | ||
39 | ** customer can send this command for sync raid volume data | ||
40 | ** 1.20.00.11 9/29/2005 Erich Chen by comment of Arjan van de Ven fix incorrect msleep redefine | ||
41 | ** cast off sizeof(dma_addr_t) condition for 64bit pci_set_dma_mask | ||
42 | ** 1.20.00.12 9/30/2005 Erich Chen bug fix with 64bit platform's ccbs using if over 4G system memory | ||
43 | ** change 64bit pci_set_consistent_dma_mask into 32bit | ||
44 | ** increcct adapter count if adapter initialize fail. | ||
45 | ** miss edit at arcmsr_build_ccb.... | ||
46 | ** psge += sizeof(struct _SG64ENTRY *) => | ||
47 | ** psge += sizeof(struct _SG64ENTRY) | ||
48 | ** 64 bits sg entry would be incorrectly calculated | ||
49 | ** thanks Kornel Wieliczek give me kindly notify | ||
50 | ** and detail description | ||
51 | ** 1.20.00.13 11/15/2005 Erich Chen scheduling pending ccb with FIFO | ||
52 | ** change the architecture of arcmsr command queue list | ||
53 | ** for linux standard list | ||
54 | ** enable usage of pci message signal interrupt | ||
55 | ** follow Randy.Danlup kindness suggestion cleanup this code | ||
56 | ************************************************************************** \ No newline at end of file | ||
diff --git a/Documentation/scsi/arcmsr_spec.txt b/Documentation/scsi/arcmsr_spec.txt new file mode 100644 index 00000000000..5e0042340fd --- /dev/null +++ b/Documentation/scsi/arcmsr_spec.txt | |||
@@ -0,0 +1,574 @@ | |||
1 | ******************************************************************************* | ||
2 | ** ARECA FIRMWARE SPEC | ||
3 | ******************************************************************************* | ||
4 | ** Usage of IOP331 adapter | ||
5 | ** (All In/Out is in IOP331's view) | ||
6 | ** 1. Message 0 --> InitThread message and retrun code | ||
7 | ** 2. Doorbell is used for RS-232 emulation | ||
8 | ** inDoorBell : bit0 -- data in ready | ||
9 | ** (DRIVER DATA WRITE OK) | ||
10 | ** bit1 -- data out has been read | ||
11 | ** (DRIVER DATA READ OK) | ||
12 | ** outDooeBell: bit0 -- data out ready | ||
13 | ** (IOP331 DATA WRITE OK) | ||
14 | ** bit1 -- data in has been read | ||
15 | ** (IOP331 DATA READ OK) | ||
16 | ** 3. Index Memory Usage | ||
17 | ** offset 0xf00 : for RS232 out (request buffer) | ||
18 | ** offset 0xe00 : for RS232 in (scratch buffer) | ||
19 | ** offset 0xa00 : for inbound message code message_rwbuffer | ||
20 | ** (driver send to IOP331) | ||
21 | ** offset 0xa00 : for outbound message code message_rwbuffer | ||
22 | ** (IOP331 send to driver) | ||
23 | ** 4. RS-232 emulation | ||
24 | ** Currently 128 byte buffer is used | ||
25 | ** 1st uint32_t : Data length (1--124) | ||
26 | ** Byte 4--127 : Max 124 bytes of data | ||
27 | ** 5. PostQ | ||
28 | ** All SCSI Command must be sent through postQ: | ||
29 | ** (inbound queue port) Request frame must be 32 bytes aligned | ||
30 | ** #bit27--bit31 => flag for post ccb | ||
31 | ** #bit0--bit26 => real address (bit27--bit31) of post arcmsr_cdb | ||
32 | ** bit31 : | ||
33 | ** 0 : 256 bytes frame | ||
34 | ** 1 : 512 bytes frame | ||
35 | ** bit30 : | ||
36 | ** 0 : normal request | ||
37 | ** 1 : BIOS request | ||
38 | ** bit29 : reserved | ||
39 | ** bit28 : reserved | ||
40 | ** bit27 : reserved | ||
41 | ** --------------------------------------------------------------------------- | ||
42 | ** (outbount queue port) Request reply | ||
43 | ** #bit27--bit31 | ||
44 | ** => flag for reply | ||
45 | ** #bit0--bit26 | ||
46 | ** => real address (bit27--bit31) of reply arcmsr_cdb | ||
47 | ** bit31 : must be 0 (for this type of reply) | ||
48 | ** bit30 : reserved for BIOS handshake | ||
49 | ** bit29 : reserved | ||
50 | ** bit28 : | ||
51 | ** 0 : no error, ignore AdapStatus/DevStatus/SenseData | ||
52 | ** 1 : Error, error code in AdapStatus/DevStatus/SenseData | ||
53 | ** bit27 : reserved | ||
54 | ** 6. BIOS request | ||
55 | ** All BIOS request is the same with request from PostQ | ||
56 | ** Except : | ||
57 | ** Request frame is sent from configuration space | ||
58 | ** offset: 0x78 : Request Frame (bit30 == 1) | ||
59 | ** offset: 0x18 : writeonly to generate | ||
60 | ** IRQ to IOP331 | ||
61 | ** Completion of request: | ||
62 | ** (bit30 == 0, bit28==err flag) | ||
63 | ** 7. Definition of SGL entry (structure) | ||
64 | ** 8. Message1 Out - Diag Status Code (????) | ||
65 | ** 9. Message0 message code : | ||
66 | ** 0x00 : NOP | ||
67 | ** 0x01 : Get Config | ||
68 | ** ->offset 0xa00 :for outbound message code message_rwbuffer | ||
69 | ** (IOP331 send to driver) | ||
70 | ** Signature 0x87974060(4) | ||
71 | ** Request len 0x00000200(4) | ||
72 | ** numbers of queue 0x00000100(4) | ||
73 | ** SDRAM Size 0x00000100(4)-->256 MB | ||
74 | ** IDE Channels 0x00000008(4) | ||
75 | ** vendor 40 bytes char | ||
76 | ** model 8 bytes char | ||
77 | ** FirmVer 16 bytes char | ||
78 | ** Device Map 16 bytes char | ||
79 | ** FirmwareVersion DWORD <== Added for checking of | ||
80 | ** new firmware capability | ||
81 | ** 0x02 : Set Config | ||
82 | ** ->offset 0xa00 :for inbound message code message_rwbuffer | ||
83 | ** (driver send to IOP331) | ||
84 | ** Signature 0x87974063(4) | ||
85 | ** UPPER32 of Request Frame (4)-->Driver Only | ||
86 | ** 0x03 : Reset (Abort all queued Command) | ||
87 | ** 0x04 : Stop Background Activity | ||
88 | ** 0x05 : Flush Cache | ||
89 | ** 0x06 : Start Background Activity | ||
90 | ** (re-start if background is halted) | ||
91 | ** 0x07 : Check If Host Command Pending | ||
92 | ** (Novell May Need This Function) | ||
93 | ** 0x08 : Set controller time | ||
94 | ** ->offset 0xa00 : for inbound message code message_rwbuffer | ||
95 | ** (driver to IOP331) | ||
96 | ** byte 0 : 0xaa <-- signature | ||
97 | ** byte 1 : 0x55 <-- signature | ||
98 | ** byte 2 : year (04) | ||
99 | ** byte 3 : month (1..12) | ||
100 | ** byte 4 : date (1..31) | ||
101 | ** byte 5 : hour (0..23) | ||
102 | ** byte 6 : minute (0..59) | ||
103 | ** byte 7 : second (0..59) | ||
104 | ******************************************************************************* | ||
105 | ******************************************************************************* | ||
106 | ** RS-232 Interface for Areca Raid Controller | ||
107 | ** The low level command interface is exclusive with VT100 terminal | ||
108 | ** -------------------------------------------------------------------- | ||
109 | ** 1. Sequence of command execution | ||
110 | ** -------------------------------------------------------------------- | ||
111 | ** (A) Header : 3 bytes sequence (0x5E, 0x01, 0x61) | ||
112 | ** (B) Command block : variable length of data including length, | ||
113 | ** command code, data and checksum byte | ||
114 | ** (C) Return data : variable length of data | ||
115 | ** -------------------------------------------------------------------- | ||
116 | ** 2. Command block | ||
117 | ** -------------------------------------------------------------------- | ||
118 | ** (A) 1st byte : command block length (low byte) | ||
119 | ** (B) 2nd byte : command block length (high byte) | ||
120 | ** note ..command block length shouldn't > 2040 bytes, | ||
121 | ** length excludes these two bytes | ||
122 | ** (C) 3rd byte : command code | ||
123 | ** (D) 4th and following bytes : variable length data bytes | ||
124 | ** depends on command code | ||
125 | ** (E) last byte : checksum byte (sum of 1st byte until last data byte) | ||
126 | ** -------------------------------------------------------------------- | ||
127 | ** 3. Command code and associated data | ||
128 | ** -------------------------------------------------------------------- | ||
129 | ** The following are command code defined in raid controller Command | ||
130 | ** code 0x10--0x1? are used for system level management, | ||
131 | ** no password checking is needed and should be implemented in separate | ||
132 | ** well controlled utility and not for end user access. | ||
133 | ** Command code 0x20--0x?? always check the password, | ||
134 | ** password must be entered to enable these command. | ||
135 | ** enum | ||
136 | ** { | ||
137 | ** GUI_SET_SERIAL=0x10, | ||
138 | ** GUI_SET_VENDOR, | ||
139 | ** GUI_SET_MODEL, | ||
140 | ** GUI_IDENTIFY, | ||
141 | ** GUI_CHECK_PASSWORD, | ||
142 | ** GUI_LOGOUT, | ||
143 | ** GUI_HTTP, | ||
144 | ** GUI_SET_ETHERNET_ADDR, | ||
145 | ** GUI_SET_LOGO, | ||
146 | ** GUI_POLL_EVENT, | ||
147 | ** GUI_GET_EVENT, | ||
148 | ** GUI_GET_HW_MONITOR, | ||
149 | ** // GUI_QUICK_CREATE=0x20, (function removed) | ||
150 | ** GUI_GET_INFO_R=0x20, | ||
151 | ** GUI_GET_INFO_V, | ||
152 | ** GUI_GET_INFO_P, | ||
153 | ** GUI_GET_INFO_S, | ||
154 | ** GUI_CLEAR_EVENT, | ||
155 | ** GUI_MUTE_BEEPER=0x30, | ||
156 | ** GUI_BEEPER_SETTING, | ||
157 | ** GUI_SET_PASSWORD, | ||
158 | ** GUI_HOST_INTERFACE_MODE, | ||
159 | ** GUI_REBUILD_PRIORITY, | ||
160 | ** GUI_MAX_ATA_MODE, | ||
161 | ** GUI_RESET_CONTROLLER, | ||
162 | ** GUI_COM_PORT_SETTING, | ||
163 | ** GUI_NO_OPERATION, | ||
164 | ** GUI_DHCP_IP, | ||
165 | ** GUI_CREATE_PASS_THROUGH=0x40, | ||
166 | ** GUI_MODIFY_PASS_THROUGH, | ||
167 | ** GUI_DELETE_PASS_THROUGH, | ||
168 | ** GUI_IDENTIFY_DEVICE, | ||
169 | ** GUI_CREATE_RAIDSET=0x50, | ||
170 | ** GUI_DELETE_RAIDSET, | ||
171 | ** GUI_EXPAND_RAIDSET, | ||
172 | ** GUI_ACTIVATE_RAIDSET, | ||
173 | ** GUI_CREATE_HOT_SPARE, | ||
174 | ** GUI_DELETE_HOT_SPARE, | ||
175 | ** GUI_CREATE_VOLUME=0x60, | ||
176 | ** GUI_MODIFY_VOLUME, | ||
177 | ** GUI_DELETE_VOLUME, | ||
178 | ** GUI_START_CHECK_VOLUME, | ||
179 | ** GUI_STOP_CHECK_VOLUME | ||
180 | ** }; | ||
181 | ** Command description : | ||
182 | ** GUI_SET_SERIAL : Set the controller serial# | ||
183 | ** byte 0,1 : length | ||
184 | ** byte 2 : command code 0x10 | ||
185 | ** byte 3 : password length (should be 0x0f) | ||
186 | ** byte 4-0x13 : should be "ArEcATecHnoLogY" | ||
187 | ** byte 0x14--0x23 : Serial number string (must be 16 bytes) | ||
188 | ** GUI_SET_VENDOR : Set vendor string for the controller | ||
189 | ** byte 0,1 : length | ||
190 | ** byte 2 : command code 0x11 | ||
191 | ** byte 3 : password length (should be 0x08) | ||
192 | ** byte 4-0x13 : should be "ArEcAvAr" | ||
193 | ** byte 0x14--0x3B : vendor string (must be 40 bytes) | ||
194 | ** GUI_SET_MODEL : Set the model name of the controller | ||
195 | ** byte 0,1 : length | ||
196 | ** byte 2 : command code 0x12 | ||
197 | ** byte 3 : password length (should be 0x08) | ||
198 | ** byte 4-0x13 : should be "ArEcAvAr" | ||
199 | ** byte 0x14--0x1B : model string (must be 8 bytes) | ||
200 | ** GUI_IDENTIFY : Identify device | ||
201 | ** byte 0,1 : length | ||
202 | ** byte 2 : command code 0x13 | ||
203 | ** return "Areca RAID Subsystem " | ||
204 | ** GUI_CHECK_PASSWORD : Verify password | ||
205 | ** byte 0,1 : length | ||
206 | ** byte 2 : command code 0x14 | ||
207 | ** byte 3 : password length | ||
208 | ** byte 4-0x?? : user password to be checked | ||
209 | ** GUI_LOGOUT : Logout GUI (force password checking on next command) | ||
210 | ** byte 0,1 : length | ||
211 | ** byte 2 : command code 0x15 | ||
212 | ** GUI_HTTP : HTTP interface (reserved for Http proxy service)(0x16) | ||
213 | ** | ||
214 | ** GUI_SET_ETHERNET_ADDR : Set the ethernet MAC address | ||
215 | ** byte 0,1 : length | ||
216 | ** byte 2 : command code 0x17 | ||
217 | ** byte 3 : password length (should be 0x08) | ||
218 | ** byte 4-0x13 : should be "ArEcAvAr" | ||
219 | ** byte 0x14--0x19 : Ethernet MAC address (must be 6 bytes) | ||
220 | ** GUI_SET_LOGO : Set logo in HTTP | ||
221 | ** byte 0,1 : length | ||
222 | ** byte 2 : command code 0x18 | ||
223 | ** byte 3 : Page# (0/1/2/3) (0xff --> clear OEM logo) | ||
224 | ** byte 4/5/6/7 : 0x55/0xaa/0xa5/0x5a | ||
225 | ** byte 8 : TITLE.JPG data (each page must be 2000 bytes) | ||
226 | ** note page0 1st 2 byte must be | ||
227 | ** actual length of the JPG file | ||
228 | ** GUI_POLL_EVENT : Poll If Event Log Changed | ||
229 | ** byte 0,1 : length | ||
230 | ** byte 2 : command code 0x19 | ||
231 | ** GUI_GET_EVENT : Read Event | ||
232 | ** byte 0,1 : length | ||
233 | ** byte 2 : command code 0x1a | ||
234 | ** byte 3 : Event Page (0:1st page/1/2/3:last page) | ||
235 | ** GUI_GET_HW_MONITOR : Get HW monitor data | ||
236 | ** byte 0,1 : length | ||
237 | ** byte 2 : command code 0x1b | ||
238 | ** byte 3 : # of FANs(example 2) | ||
239 | ** byte 4 : # of Voltage sensor(example 3) | ||
240 | ** byte 5 : # of temperature sensor(example 2) | ||
241 | ** byte 6 : # of power | ||
242 | ** byte 7/8 : Fan#0 (RPM) | ||
243 | ** byte 9/10 : Fan#1 | ||
244 | ** byte 11/12 : Voltage#0 original value in *1000 | ||
245 | ** byte 13/14 : Voltage#0 value | ||
246 | ** byte 15/16 : Voltage#1 org | ||
247 | ** byte 17/18 : Voltage#1 | ||
248 | ** byte 19/20 : Voltage#2 org | ||
249 | ** byte 21/22 : Voltage#2 | ||
250 | ** byte 23 : Temp#0 | ||
251 | ** byte 24 : Temp#1 | ||
252 | ** byte 25 : Power indicator (bit0 : power#0, | ||
253 | ** bit1 : power#1) | ||
254 | ** byte 26 : UPS indicator | ||
255 | ** GUI_QUICK_CREATE : Quick create raid/volume set | ||
256 | ** byte 0,1 : length | ||
257 | ** byte 2 : command code 0x20 | ||
258 | ** byte 3/4/5/6 : raw capacity | ||
259 | ** byte 7 : raid level | ||
260 | ** byte 8 : stripe size | ||
261 | ** byte 9 : spare | ||
262 | ** byte 10/11/12/13: device mask (the devices to create raid/volume) | ||
263 | ** This function is removed, application like | ||
264 | ** to implement quick create function | ||
265 | ** need to use GUI_CREATE_RAIDSET and GUI_CREATE_VOLUMESET function. | ||
266 | ** GUI_GET_INFO_R : Get Raid Set Information | ||
267 | ** byte 0,1 : length | ||
268 | ** byte 2 : command code 0x20 | ||
269 | ** byte 3 : raidset# | ||
270 | ** typedef struct sGUI_RAIDSET | ||
271 | ** { | ||
272 | ** BYTE grsRaidSetName[16]; | ||
273 | ** DWORD grsCapacity; | ||
274 | ** DWORD grsCapacityX; | ||
275 | ** DWORD grsFailMask; | ||
276 | ** BYTE grsDevArray[32]; | ||
277 | ** BYTE grsMemberDevices; | ||
278 | ** BYTE grsNewMemberDevices; | ||
279 | ** BYTE grsRaidState; | ||
280 | ** BYTE grsVolumes; | ||
281 | ** BYTE grsVolumeList[16]; | ||
282 | ** BYTE grsRes1; | ||
283 | ** BYTE grsRes2; | ||
284 | ** BYTE grsRes3; | ||
285 | ** BYTE grsFreeSegments; | ||
286 | ** DWORD grsRawStripes[8]; | ||
287 | ** DWORD grsRes4; | ||
288 | ** DWORD grsRes5; // Total to 128 bytes | ||
289 | ** DWORD grsRes6; // Total to 128 bytes | ||
290 | ** } sGUI_RAIDSET, *pGUI_RAIDSET; | ||
291 | ** GUI_GET_INFO_V : Get Volume Set Information | ||
292 | ** byte 0,1 : length | ||
293 | ** byte 2 : command code 0x21 | ||
294 | ** byte 3 : volumeset# | ||
295 | ** typedef struct sGUI_VOLUMESET | ||
296 | ** { | ||
297 | ** BYTE gvsVolumeName[16]; // 16 | ||
298 | ** DWORD gvsCapacity; | ||
299 | ** DWORD gvsCapacityX; | ||
300 | ** DWORD gvsFailMask; | ||
301 | ** DWORD gvsStripeSize; | ||
302 | ** DWORD gvsNewFailMask; | ||
303 | ** DWORD gvsNewStripeSize; | ||
304 | ** DWORD gvsVolumeStatus; | ||
305 | ** DWORD gvsProgress; // 32 | ||
306 | ** sSCSI_ATTR gvsScsi; | ||
307 | ** BYTE gvsMemberDisks; | ||
308 | ** BYTE gvsRaidLevel; // 8 | ||
309 | ** BYTE gvsNewMemberDisks; | ||
310 | ** BYTE gvsNewRaidLevel; | ||
311 | ** BYTE gvsRaidSetNumber; | ||
312 | ** BYTE gvsRes0; // 4 | ||
313 | ** BYTE gvsRes1[4]; // 64 bytes | ||
314 | ** } sGUI_VOLUMESET, *pGUI_VOLUMESET; | ||
315 | ** GUI_GET_INFO_P : Get Physical Drive Information | ||
316 | ** byte 0,1 : length | ||
317 | ** byte 2 : command code 0x22 | ||
318 | ** byte 3 : drive # (from 0 to max-channels - 1) | ||
319 | ** typedef struct sGUI_PHY_DRV | ||
320 | ** { | ||
321 | ** BYTE gpdModelName[40]; | ||
322 | ** BYTE gpdSerialNumber[20]; | ||
323 | ** BYTE gpdFirmRev[8]; | ||
324 | ** DWORD gpdCapacity; | ||
325 | ** DWORD gpdCapacityX; // Reserved for expansion | ||
326 | ** BYTE gpdDeviceState; | ||
327 | ** BYTE gpdPioMode; | ||
328 | ** BYTE gpdCurrentUdmaMode; | ||
329 | ** BYTE gpdUdmaMode; | ||
330 | ** BYTE gpdDriveSelect; | ||
331 | ** BYTE gpdRaidNumber; // 0xff if not belongs to a raid set | ||
332 | ** sSCSI_ATTR gpdScsi; | ||
333 | ** BYTE gpdReserved[40]; // Total to 128 bytes | ||
334 | ** } sGUI_PHY_DRV, *pGUI_PHY_DRV; | ||
335 | ** GUI_GET_INFO_S : Get System Information | ||
336 | ** byte 0,1 : length | ||
337 | ** byte 2 : command code 0x23 | ||
338 | ** typedef struct sCOM_ATTR | ||
339 | ** { | ||
340 | ** BYTE comBaudRate; | ||
341 | ** BYTE comDataBits; | ||
342 | ** BYTE comStopBits; | ||
343 | ** BYTE comParity; | ||
344 | ** BYTE comFlowControl; | ||
345 | ** } sCOM_ATTR, *pCOM_ATTR; | ||
346 | ** typedef struct sSYSTEM_INFO | ||
347 | ** { | ||
348 | ** BYTE gsiVendorName[40]; | ||
349 | ** BYTE gsiSerialNumber[16]; | ||
350 | ** BYTE gsiFirmVersion[16]; | ||
351 | ** BYTE gsiBootVersion[16]; | ||
352 | ** BYTE gsiMbVersion[16]; | ||
353 | ** BYTE gsiModelName[8]; | ||
354 | ** BYTE gsiLocalIp[4]; | ||
355 | ** BYTE gsiCurrentIp[4]; | ||
356 | ** DWORD gsiTimeTick; | ||
357 | ** DWORD gsiCpuSpeed; | ||
358 | ** DWORD gsiICache; | ||
359 | ** DWORD gsiDCache; | ||
360 | ** DWORD gsiScache; | ||
361 | ** DWORD gsiMemorySize; | ||
362 | ** DWORD gsiMemorySpeed; | ||
363 | ** DWORD gsiEvents; | ||
364 | ** BYTE gsiMacAddress[6]; | ||
365 | ** BYTE gsiDhcp; | ||
366 | ** BYTE gsiBeeper; | ||
367 | ** BYTE gsiChannelUsage; | ||
368 | ** BYTE gsiMaxAtaMode; | ||
369 | ** BYTE gsiSdramEcc; // 1:if ECC enabled | ||
370 | ** BYTE gsiRebuildPriority; | ||
371 | ** sCOM_ATTR gsiComA; // 5 bytes | ||
372 | ** sCOM_ATTR gsiComB; // 5 bytes | ||
373 | ** BYTE gsiIdeChannels; | ||
374 | ** BYTE gsiScsiHostChannels; | ||
375 | ** BYTE gsiIdeHostChannels; | ||
376 | ** BYTE gsiMaxVolumeSet; | ||
377 | ** BYTE gsiMaxRaidSet; | ||
378 | ** BYTE gsiEtherPort; // 1:if ether net port supported | ||
379 | ** BYTE gsiRaid6Engine; // 1:Raid6 engine supported | ||
380 | ** BYTE gsiRes[75]; | ||
381 | ** } sSYSTEM_INFO, *pSYSTEM_INFO; | ||
382 | ** GUI_CLEAR_EVENT : Clear System Event | ||
383 | ** byte 0,1 : length | ||
384 | ** byte 2 : command code 0x24 | ||
385 | ** GUI_MUTE_BEEPER : Mute current beeper | ||
386 | ** byte 0,1 : length | ||
387 | ** byte 2 : command code 0x30 | ||
388 | ** GUI_BEEPER_SETTING : Disable beeper | ||
389 | ** byte 0,1 : length | ||
390 | ** byte 2 : command code 0x31 | ||
391 | ** byte 3 : 0->disable, 1->enable | ||
392 | ** GUI_SET_PASSWORD : Change password | ||
393 | ** byte 0,1 : length | ||
394 | ** byte 2 : command code 0x32 | ||
395 | ** byte 3 : pass word length ( must <= 15 ) | ||
396 | ** byte 4 : password (must be alpha-numerical) | ||
397 | ** GUI_HOST_INTERFACE_MODE : Set host interface mode | ||
398 | ** byte 0,1 : length | ||
399 | ** byte 2 : command code 0x33 | ||
400 | ** byte 3 : 0->Independent, 1->cluster | ||
401 | ** GUI_REBUILD_PRIORITY : Set rebuild priority | ||
402 | ** byte 0,1 : length | ||
403 | ** byte 2 : command code 0x34 | ||
404 | ** byte 3 : 0/1/2/3 (low->high) | ||
405 | ** GUI_MAX_ATA_MODE : Set maximum ATA mode to be used | ||
406 | ** byte 0,1 : length | ||
407 | ** byte 2 : command code 0x35 | ||
408 | ** byte 3 : 0/1/2/3 (133/100/66/33) | ||
409 | ** GUI_RESET_CONTROLLER : Reset Controller | ||
410 | ** byte 0,1 : length | ||
411 | ** byte 2 : command code 0x36 | ||
412 | ** *Response with VT100 screen (discard it) | ||
413 | ** GUI_COM_PORT_SETTING : COM port setting | ||
414 | ** byte 0,1 : length | ||
415 | ** byte 2 : command code 0x37 | ||
416 | ** byte 3 : 0->COMA (term port), | ||
417 | ** 1->COMB (debug port) | ||
418 | ** byte 4 : 0/1/2/3/4/5/6/7 | ||
419 | ** (1200/2400/4800/9600/19200/38400/57600/115200) | ||
420 | ** byte 5 : data bit | ||
421 | ** (0:7 bit, 1:8 bit : must be 8 bit) | ||
422 | ** byte 6 : stop bit (0:1, 1:2 stop bits) | ||
423 | ** byte 7 : parity (0:none, 1:off, 2:even) | ||
424 | ** byte 8 : flow control | ||
425 | ** (0:none, 1:xon/xoff, 2:hardware => must use none) | ||
426 | ** GUI_NO_OPERATION : No operation | ||
427 | ** byte 0,1 : length | ||
428 | ** byte 2 : command code 0x38 | ||
429 | ** GUI_DHCP_IP : Set DHCP option and local IP address | ||
430 | ** byte 0,1 : length | ||
431 | ** byte 2 : command code 0x39 | ||
432 | ** byte 3 : 0:dhcp disabled, 1:dhcp enabled | ||
433 | ** byte 4/5/6/7 : IP address | ||
434 | ** GUI_CREATE_PASS_THROUGH : Create pass through disk | ||
435 | ** byte 0,1 : length | ||
436 | ** byte 2 : command code 0x40 | ||
437 | ** byte 3 : device # | ||
438 | ** byte 4 : scsi channel (0/1) | ||
439 | ** byte 5 : scsi id (0-->15) | ||
440 | ** byte 6 : scsi lun (0-->7) | ||
441 | ** byte 7 : tagged queue (1 : enabled) | ||
442 | ** byte 8 : cache mode (1 : enabled) | ||
443 | ** byte 9 : max speed (0/1/2/3/4, | ||
444 | ** async/20/40/80/160 for scsi) | ||
445 | ** (0/1/2/3/4, 33/66/100/133/150 for ide ) | ||
446 | ** GUI_MODIFY_PASS_THROUGH : Modify pass through disk | ||
447 | ** byte 0,1 : length | ||
448 | ** byte 2 : command code 0x41 | ||
449 | ** byte 3 : device # | ||
450 | ** byte 4 : scsi channel (0/1) | ||
451 | ** byte 5 : scsi id (0-->15) | ||
452 | ** byte 6 : scsi lun (0-->7) | ||
453 | ** byte 7 : tagged queue (1 : enabled) | ||
454 | ** byte 8 : cache mode (1 : enabled) | ||
455 | ** byte 9 : max speed (0/1/2/3/4, | ||
456 | ** async/20/40/80/160 for scsi) | ||
457 | ** (0/1/2/3/4, 33/66/100/133/150 for ide ) | ||
458 | ** GUI_DELETE_PASS_THROUGH : Delete pass through disk | ||
459 | ** byte 0,1 : length | ||
460 | ** byte 2 : command code 0x42 | ||
461 | ** byte 3 : device# to be deleted | ||
462 | ** GUI_IDENTIFY_DEVICE : Identify Device | ||
463 | ** byte 0,1 : length | ||
464 | ** byte 2 : command code 0x43 | ||
465 | ** byte 3 : Flash Method | ||
466 | ** (0:flash selected, 1:flash not selected) | ||
467 | ** byte 4/5/6/7 : IDE device mask to be flashed | ||
468 | ** note .... no response data available | ||
469 | ** GUI_CREATE_RAIDSET : Create Raid Set | ||
470 | ** byte 0,1 : length | ||
471 | ** byte 2 : command code 0x50 | ||
472 | ** byte 3/4/5/6 : device mask | ||
473 | ** byte 7-22 : raidset name (if byte 7 == 0:use default) | ||
474 | ** GUI_DELETE_RAIDSET : Delete Raid Set | ||
475 | ** byte 0,1 : length | ||
476 | ** byte 2 : command code 0x51 | ||
477 | ** byte 3 : raidset# | ||
478 | ** GUI_EXPAND_RAIDSET : Expand Raid Set | ||
479 | ** byte 0,1 : length | ||
480 | ** byte 2 : command code 0x52 | ||
481 | ** byte 3 : raidset# | ||
482 | ** byte 4/5/6/7 : device mask for expansion | ||
483 | ** byte 8/9/10 : (8:0 no change, 1 change, 0xff:terminate, | ||
484 | ** 9:new raid level, | ||
485 | ** 10:new stripe size | ||
486 | ** 0/1/2/3/4/5->4/8/16/32/64/128K ) | ||
487 | ** byte 11/12/13 : repeat for each volume in the raidset | ||
488 | ** GUI_ACTIVATE_RAIDSET : Activate incomplete raid set | ||
489 | ** byte 0,1 : length | ||
490 | ** byte 2 : command code 0x53 | ||
491 | ** byte 3 : raidset# | ||
492 | ** GUI_CREATE_HOT_SPARE : Create hot spare disk | ||
493 | ** byte 0,1 : length | ||
494 | ** byte 2 : command code 0x54 | ||
495 | ** byte 3/4/5/6 : device mask for hot spare creation | ||
496 | ** GUI_DELETE_HOT_SPARE : Delete hot spare disk | ||
497 | ** byte 0,1 : length | ||
498 | ** byte 2 : command code 0x55 | ||
499 | ** byte 3/4/5/6 : device mask for hot spare deletion | ||
500 | ** GUI_CREATE_VOLUME : Create volume set | ||
501 | ** byte 0,1 : length | ||
502 | ** byte 2 : command code 0x60 | ||
503 | ** byte 3 : raidset# | ||
504 | ** byte 4-19 : volume set name | ||
505 | ** (if byte4 == 0, use default) | ||
506 | ** byte 20-27 : volume capacity (blocks) | ||
507 | ** byte 28 : raid level | ||
508 | ** byte 29 : stripe size | ||
509 | ** (0/1/2/3/4/5->4/8/16/32/64/128K) | ||
510 | ** byte 30 : channel | ||
511 | ** byte 31 : ID | ||
512 | ** byte 32 : LUN | ||
513 | ** byte 33 : 1 enable tag | ||
514 | ** byte 34 : 1 enable cache | ||
515 | ** byte 35 : speed | ||
516 | ** (0/1/2/3/4->async/20/40/80/160 for scsi) | ||
517 | ** (0/1/2/3/4->33/66/100/133/150 for IDE ) | ||
518 | ** byte 36 : 1 to select quick init | ||
519 | ** | ||
520 | ** GUI_MODIFY_VOLUME : Modify volume Set | ||
521 | ** byte 0,1 : length | ||
522 | ** byte 2 : command code 0x61 | ||
523 | ** byte 3 : volumeset# | ||
524 | ** byte 4-19 : new volume set name | ||
525 | ** (if byte4 == 0, not change) | ||
526 | ** byte 20-27 : new volume capacity (reserved) | ||
527 | ** byte 28 : new raid level | ||
528 | ** byte 29 : new stripe size | ||
529 | ** (0/1/2/3/4/5->4/8/16/32/64/128K) | ||
530 | ** byte 30 : new channel | ||
531 | ** byte 31 : new ID | ||
532 | ** byte 32 : new LUN | ||
533 | ** byte 33 : 1 enable tag | ||
534 | ** byte 34 : 1 enable cache | ||
535 | ** byte 35 : speed | ||
536 | ** (0/1/2/3/4->async/20/40/80/160 for scsi) | ||
537 | ** (0/1/2/3/4->33/66/100/133/150 for IDE ) | ||
538 | ** GUI_DELETE_VOLUME : Delete volume set | ||
539 | ** byte 0,1 : length | ||
540 | ** byte 2 : command code 0x62 | ||
541 | ** byte 3 : volumeset# | ||
542 | ** GUI_START_CHECK_VOLUME : Start volume consistency check | ||
543 | ** byte 0,1 : length | ||
544 | ** byte 2 : command code 0x63 | ||
545 | ** byte 3 : volumeset# | ||
546 | ** GUI_STOP_CHECK_VOLUME : Stop volume consistency check | ||
547 | ** byte 0,1 : length | ||
548 | ** byte 2 : command code 0x64 | ||
549 | ** --------------------------------------------------------------------- | ||
550 | ** 4. Returned data | ||
551 | ** --------------------------------------------------------------------- | ||
552 | ** (A) Header : 3 bytes sequence (0x5E, 0x01, 0x61) | ||
553 | ** (B) Length : 2 bytes | ||
554 | ** (low byte 1st, excludes length and checksum byte) | ||
555 | ** (C) status or data : | ||
556 | ** <1> If length == 1 ==> 1 byte status code | ||
557 | ** #define GUI_OK 0x41 | ||
558 | ** #define GUI_RAIDSET_NOT_NORMAL 0x42 | ||
559 | ** #define GUI_VOLUMESET_NOT_NORMAL 0x43 | ||
560 | ** #define GUI_NO_RAIDSET 0x44 | ||
561 | ** #define GUI_NO_VOLUMESET 0x45 | ||
562 | ** #define GUI_NO_PHYSICAL_DRIVE 0x46 | ||
563 | ** #define GUI_PARAMETER_ERROR 0x47 | ||
564 | ** #define GUI_UNSUPPORTED_COMMAND 0x48 | ||
565 | ** #define GUI_DISK_CONFIG_CHANGED 0x49 | ||
566 | ** #define GUI_INVALID_PASSWORD 0x4a | ||
567 | ** #define GUI_NO_DISK_SPACE 0x4b | ||
568 | ** #define GUI_CHECKSUM_ERROR 0x4c | ||
569 | ** #define GUI_PASSWORD_REQUIRED 0x4d | ||
570 | ** <2> If length > 1 ==> | ||
571 | ** data block returned from controller | ||
572 | ** and the contents depends on the command code | ||
573 | ** (E) Checksum : checksum of length and status or data byte | ||
574 | ************************************************************************** | ||
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 4cd23c3eab4..a360215dbce 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c | |||
@@ -7115,7 +7115,7 @@ static struct pci_device_id DAC960_id_table[] = { | |||
7115 | { | 7115 | { |
7116 | .vendor = PCI_VENDOR_ID_MYLEX, | 7116 | .vendor = PCI_VENDOR_ID_MYLEX, |
7117 | .device = PCI_DEVICE_ID_MYLEX_DAC960_GEM, | 7117 | .device = PCI_DEVICE_ID_MYLEX_DAC960_GEM, |
7118 | .subvendor = PCI_ANY_ID, | 7118 | .subvendor = PCI_VENDOR_ID_MYLEX, |
7119 | .subdevice = PCI_ANY_ID, | 7119 | .subdevice = PCI_ANY_ID, |
7120 | .driver_data = (unsigned long) &DAC960_GEM_privdata, | 7120 | .driver_data = (unsigned long) &DAC960_GEM_privdata, |
7121 | }, | 7121 | }, |
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index afdff32f672..05f79d7393f 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c | |||
@@ -251,10 +251,6 @@ scsi_cmd_stack_free(int ctlr) | |||
251 | stk->pool = NULL; | 251 | stk->pool = NULL; |
252 | } | 252 | } |
253 | 253 | ||
254 | /* scsi_device_types comes from scsi.h */ | ||
255 | #define DEVICETYPE(n) (n<0 || n>MAX_SCSI_DEVICE_CODE) ? \ | ||
256 | "Unknown" : scsi_device_types[n] | ||
257 | |||
258 | #if 0 | 254 | #if 0 |
259 | static int xmargin=8; | 255 | static int xmargin=8; |
260 | static int amargin=60; | 256 | static int amargin=60; |
@@ -389,7 +385,7 @@ cciss_scsi_add_entry(int ctlr, int hostno, | |||
389 | time anyway (the scsi layer's inquiries will show that info) */ | 385 | time anyway (the scsi layer's inquiries will show that info) */ |
390 | if (hostno != -1) | 386 | if (hostno != -1) |
391 | printk("cciss%d: %s device c%db%dt%dl%d added.\n", | 387 | printk("cciss%d: %s device c%db%dt%dl%d added.\n", |
392 | ctlr, DEVICETYPE(sd->devtype), hostno, | 388 | ctlr, scsi_device_type(sd->devtype), hostno, |
393 | sd->bus, sd->target, sd->lun); | 389 | sd->bus, sd->target, sd->lun); |
394 | return 0; | 390 | return 0; |
395 | } | 391 | } |
@@ -407,7 +403,7 @@ cciss_scsi_remove_entry(int ctlr, int hostno, int entry) | |||
407 | ccissscsi[ctlr].dev[i] = ccissscsi[ctlr].dev[i+1]; | 403 | ccissscsi[ctlr].dev[i] = ccissscsi[ctlr].dev[i+1]; |
408 | ccissscsi[ctlr].ndevices--; | 404 | ccissscsi[ctlr].ndevices--; |
409 | printk("cciss%d: %s device c%db%dt%dl%d removed.\n", | 405 | printk("cciss%d: %s device c%db%dt%dl%d removed.\n", |
410 | ctlr, DEVICETYPE(sd.devtype), hostno, | 406 | ctlr, scsi_device_type(sd.devtype), hostno, |
411 | sd.bus, sd.target, sd.lun); | 407 | sd.bus, sd.target, sd.lun); |
412 | } | 408 | } |
413 | 409 | ||
@@ -458,7 +454,7 @@ adjust_cciss_scsi_table(int ctlr, int hostno, | |||
458 | if (found == 0) { /* device no longer present. */ | 454 | if (found == 0) { /* device no longer present. */ |
459 | changes++; | 455 | changes++; |
460 | /* printk("cciss%d: %s device c%db%dt%dl%d removed.\n", | 456 | /* printk("cciss%d: %s device c%db%dt%dl%d removed.\n", |
461 | ctlr, DEVICETYPE(csd->devtype), hostno, | 457 | ctlr, scsi_device_type(csd->devtype), hostno, |
462 | csd->bus, csd->target, csd->lun); */ | 458 | csd->bus, csd->target, csd->lun); */ |
463 | cciss_scsi_remove_entry(ctlr, hostno, i); | 459 | cciss_scsi_remove_entry(ctlr, hostno, i); |
464 | /* note, i not incremented */ | 460 | /* note, i not incremented */ |
@@ -468,7 +464,7 @@ adjust_cciss_scsi_table(int ctlr, int hostno, | |||
468 | printk("cciss%d: device c%db%dt%dl%d type changed " | 464 | printk("cciss%d: device c%db%dt%dl%d type changed " |
469 | "(device type now %s).\n", | 465 | "(device type now %s).\n", |
470 | ctlr, hostno, csd->bus, csd->target, csd->lun, | 466 | ctlr, hostno, csd->bus, csd->target, csd->lun, |
471 | DEVICETYPE(csd->devtype)); | 467 | scsi_device_type(csd->devtype)); |
472 | csd->devtype = sd[j].devtype; | 468 | csd->devtype = sd[j].devtype; |
473 | i++; /* so just move along. */ | 469 | i++; /* so just move along. */ |
474 | } else /* device is same as it ever was, */ | 470 | } else /* device is same as it ever was, */ |
@@ -1098,7 +1094,7 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) | |||
1098 | if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) { | 1094 | if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) { |
1099 | printk(KERN_INFO "cciss%d: %s ignored, " | 1095 | printk(KERN_INFO "cciss%d: %s ignored, " |
1100 | "too many devices.\n", cntl_num, | 1096 | "too many devices.\n", cntl_num, |
1101 | DEVICETYPE(devtype)); | 1097 | scsi_device_type(devtype)); |
1102 | break; | 1098 | break; |
1103 | } | 1099 | } |
1104 | memcpy(¤tsd[ncurrent].scsi3addr[0], | 1100 | memcpy(¤tsd[ncurrent].scsi3addr[0], |
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 85696f34c31..e57bb035a02 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c | |||
@@ -162,7 +162,13 @@ static struct fc_function_template mptfc_transport_functions = { | |||
162 | .show_starget_port_id = 1, | 162 | .show_starget_port_id = 1, |
163 | .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo, | 163 | .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo, |
164 | .show_rport_dev_loss_tmo = 1, | 164 | .show_rport_dev_loss_tmo = 1, |
165 | 165 | .show_host_supported_speeds = 1, | |
166 | .show_host_maxframe_size = 1, | ||
167 | .show_host_speed = 1, | ||
168 | .show_host_fabric_name = 1, | ||
169 | .show_host_port_type = 1, | ||
170 | .show_host_port_state = 1, | ||
171 | .show_host_symbolic_name = 1, | ||
166 | }; | 172 | }; |
167 | 173 | ||
168 | static void | 174 | static void |
@@ -839,33 +845,95 @@ mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc) | |||
839 | static void | 845 | static void |
840 | mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) | 846 | mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) |
841 | { | 847 | { |
842 | unsigned class = 0, cos = 0; | 848 | unsigned class = 0; |
849 | unsigned cos = 0; | ||
850 | unsigned speed; | ||
851 | unsigned port_type; | ||
852 | unsigned port_state; | ||
853 | FCPortPage0_t *pp0; | ||
854 | struct Scsi_Host *sh; | ||
855 | char *sn; | ||
843 | 856 | ||
844 | /* don't know what to do as only one scsi (fc) host was allocated */ | 857 | /* don't know what to do as only one scsi (fc) host was allocated */ |
845 | if (portnum != 0) | 858 | if (portnum != 0) |
846 | return; | 859 | return; |
847 | 860 | ||
848 | class = ioc->fc_port_page0[portnum].SupportedServiceClass; | 861 | pp0 = &ioc->fc_port_page0[portnum]; |
862 | sh = ioc->sh; | ||
863 | |||
864 | sn = fc_host_symbolic_name(sh); | ||
865 | snprintf(sn, FC_SYMBOLIC_NAME_SIZE, "%s %s%08xh", | ||
866 | ioc->prod_name, | ||
867 | MPT_FW_REV_MAGIC_ID_STRING, | ||
868 | ioc->facts.FWVersion.Word); | ||
869 | |||
870 | fc_host_tgtid_bind_type(sh) = FC_TGTID_BIND_BY_WWPN; | ||
871 | |||
872 | fc_host_maxframe_size(sh) = pp0->MaxFrameSize; | ||
873 | |||
874 | fc_host_node_name(sh) = | ||
875 | (u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low; | ||
876 | |||
877 | fc_host_port_name(sh) = | ||
878 | (u64)pp0->WWPN.High << 32 | (u64)pp0->WWPN.Low; | ||
879 | |||
880 | fc_host_port_id(sh) = pp0->PortIdentifier; | ||
881 | |||
882 | class = pp0->SupportedServiceClass; | ||
849 | if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1) | 883 | if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1) |
850 | cos |= FC_COS_CLASS1; | 884 | cos |= FC_COS_CLASS1; |
851 | if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2) | 885 | if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2) |
852 | cos |= FC_COS_CLASS2; | 886 | cos |= FC_COS_CLASS2; |
853 | if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3) | 887 | if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3) |
854 | cos |= FC_COS_CLASS3; | 888 | cos |= FC_COS_CLASS3; |
889 | fc_host_supported_classes(sh) = cos; | ||
890 | |||
891 | if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT) | ||
892 | speed = FC_PORTSPEED_1GBIT; | ||
893 | else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT) | ||
894 | speed = FC_PORTSPEED_2GBIT; | ||
895 | else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT) | ||
896 | speed = FC_PORTSPEED_4GBIT; | ||
897 | else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT) | ||
898 | speed = FC_PORTSPEED_10GBIT; | ||
899 | else | ||
900 | speed = FC_PORTSPEED_UNKNOWN; | ||
901 | fc_host_speed(sh) = speed; | ||
902 | |||
903 | speed = 0; | ||
904 | if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED) | ||
905 | speed |= FC_PORTSPEED_1GBIT; | ||
906 | if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED) | ||
907 | speed |= FC_PORTSPEED_2GBIT; | ||
908 | if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED) | ||
909 | speed |= FC_PORTSPEED_4GBIT; | ||
910 | if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED) | ||
911 | speed |= FC_PORTSPEED_10GBIT; | ||
912 | fc_host_supported_speeds(sh) = speed; | ||
913 | |||
914 | port_state = FC_PORTSTATE_UNKNOWN; | ||
915 | if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE) | ||
916 | port_state = FC_PORTSTATE_ONLINE; | ||
917 | else if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_OFFLINE) | ||
918 | port_state = FC_PORTSTATE_LINKDOWN; | ||
919 | fc_host_port_state(sh) = port_state; | ||
920 | |||
921 | port_type = FC_PORTTYPE_UNKNOWN; | ||
922 | if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT) | ||
923 | port_type = FC_PORTTYPE_PTP; | ||
924 | else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP) | ||
925 | port_type = FC_PORTTYPE_LPORT; | ||
926 | else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP) | ||
927 | port_type = FC_PORTTYPE_NLPORT; | ||
928 | else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT) | ||
929 | port_type = FC_PORTTYPE_NPORT; | ||
930 | fc_host_port_type(sh) = port_type; | ||
931 | |||
932 | fc_host_fabric_name(sh) = | ||
933 | (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_FABRIC_WWN_VALID) ? | ||
934 | (u64) pp0->FabricWWNN.High << 32 | (u64) pp0->FabricWWPN.Low : | ||
935 | (u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low; | ||
855 | 936 | ||
856 | fc_host_node_name(ioc->sh) = | ||
857 | (u64)ioc->fc_port_page0[portnum].WWNN.High << 32 | ||
858 | | (u64)ioc->fc_port_page0[portnum].WWNN.Low; | ||
859 | |||
860 | fc_host_port_name(ioc->sh) = | ||
861 | (u64)ioc->fc_port_page0[portnum].WWPN.High << 32 | ||
862 | | (u64)ioc->fc_port_page0[portnum].WWPN.Low; | ||
863 | |||
864 | fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier; | ||
865 | |||
866 | fc_host_supported_classes(ioc->sh) = cos; | ||
867 | |||
868 | fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN; | ||
869 | } | 937 | } |
870 | 938 | ||
871 | static void | 939 | static void |
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index f66f2203143..dfdd1e44576 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c | |||
@@ -1642,14 +1642,18 @@ static int mptsas_probe_one_phy(struct device *dev, | |||
1642 | 1642 | ||
1643 | for (i = 0; i < port_info->num_phys; i++) | 1643 | for (i = 0; i < port_info->num_phys; i++) |
1644 | if (port_info->phy_info[i].identify.sas_address == | 1644 | if (port_info->phy_info[i].identify.sas_address == |
1645 | identify.sas_address) | 1645 | identify.sas_address) { |
1646 | sas_port_mark_backlink(port); | ||
1646 | goto out; | 1647 | goto out; |
1648 | } | ||
1647 | 1649 | ||
1648 | } else if (scsi_is_sas_rphy(parent)) { | 1650 | } else if (scsi_is_sas_rphy(parent)) { |
1649 | struct sas_rphy *parent_rphy = dev_to_rphy(parent); | 1651 | struct sas_rphy *parent_rphy = dev_to_rphy(parent); |
1650 | if (identify.sas_address == | 1652 | if (identify.sas_address == |
1651 | parent_rphy->identify.sas_address) | 1653 | parent_rphy->identify.sas_address) { |
1654 | sas_port_mark_backlink(port); | ||
1652 | goto out; | 1655 | goto out; |
1656 | } | ||
1653 | } | 1657 | } |
1654 | 1658 | ||
1655 | switch (identify.device_type) { | 1659 | switch (identify.device_type) { |
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 16a12a3b7b2..59d1adaed73 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c | |||
@@ -2176,6 +2176,7 @@ static int __init BusLogic_init(void) | |||
2176 | { | 2176 | { |
2177 | int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex; | 2177 | int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex; |
2178 | struct BusLogic_HostAdapter *PrototypeHostAdapter; | 2178 | struct BusLogic_HostAdapter *PrototypeHostAdapter; |
2179 | int ret = 0; | ||
2179 | 2180 | ||
2180 | #ifdef MODULE | 2181 | #ifdef MODULE |
2181 | if (BusLogic) | 2182 | if (BusLogic) |
@@ -2282,25 +2283,49 @@ static int __init BusLogic_init(void) | |||
2282 | perform Target Device Inquiry. | 2283 | perform Target Device Inquiry. |
2283 | */ | 2284 | */ |
2284 | if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) && | 2285 | if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) && |
2285 | BusLogic_ReportHostAdapterConfiguration(HostAdapter) && BusLogic_AcquireResources(HostAdapter) && BusLogic_CreateInitialCCBs(HostAdapter) && BusLogic_InitializeHostAdapter(HostAdapter) && BusLogic_TargetDeviceInquiry(HostAdapter)) { | 2286 | BusLogic_ReportHostAdapterConfiguration(HostAdapter) && |
2287 | BusLogic_AcquireResources(HostAdapter) && | ||
2288 | BusLogic_CreateInitialCCBs(HostAdapter) && | ||
2289 | BusLogic_InitializeHostAdapter(HostAdapter) && | ||
2290 | BusLogic_TargetDeviceInquiry(HostAdapter)) { | ||
2286 | /* | 2291 | /* |
2287 | Initialization has been completed successfully. Release and | 2292 | Initialization has been completed successfully. Release and |
2288 | re-register usage of the I/O Address range so that the Model | 2293 | re-register usage of the I/O Address range so that the Model |
2289 | Name of the Host Adapter will appear, and initialize the SCSI | 2294 | Name of the Host Adapter will appear, and initialize the SCSI |
2290 | Host structure. | 2295 | Host structure. |
2291 | */ | 2296 | */ |
2292 | release_region(HostAdapter->IO_Address, HostAdapter->AddressCount); | 2297 | release_region(HostAdapter->IO_Address, |
2293 | if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, HostAdapter->FullModelName)) { | 2298 | HostAdapter->AddressCount); |
2294 | printk(KERN_WARNING "BusLogic: Release and re-register of " "port 0x%04lx failed \n", (unsigned long) HostAdapter->IO_Address); | 2299 | if (!request_region(HostAdapter->IO_Address, |
2300 | HostAdapter->AddressCount, | ||
2301 | HostAdapter->FullModelName)) { | ||
2302 | printk(KERN_WARNING | ||
2303 | "BusLogic: Release and re-register of " | ||
2304 | "port 0x%04lx failed \n", | ||
2305 | (unsigned long)HostAdapter->IO_Address); | ||
2295 | BusLogic_DestroyCCBs(HostAdapter); | 2306 | BusLogic_DestroyCCBs(HostAdapter); |
2296 | BusLogic_ReleaseResources(HostAdapter); | 2307 | BusLogic_ReleaseResources(HostAdapter); |
2297 | list_del(&HostAdapter->host_list); | 2308 | list_del(&HostAdapter->host_list); |
2298 | scsi_host_put(Host); | 2309 | scsi_host_put(Host); |
2310 | ret = -ENOMEM; | ||
2299 | } else { | 2311 | } else { |
2300 | BusLogic_InitializeHostStructure(HostAdapter, Host); | 2312 | BusLogic_InitializeHostStructure(HostAdapter, |
2301 | scsi_add_host(Host, HostAdapter->PCI_Device ? &HostAdapter->PCI_Device->dev : NULL); | 2313 | Host); |
2302 | scsi_scan_host(Host); | 2314 | if (scsi_add_host(Host, HostAdapter->PCI_Device |
2303 | BusLogicHostAdapterCount++; | 2315 | ? &HostAdapter->PCI_Device->dev |
2316 | : NULL)) { | ||
2317 | printk(KERN_WARNING | ||
2318 | "BusLogic: scsi_add_host()" | ||
2319 | "failed!\n"); | ||
2320 | BusLogic_DestroyCCBs(HostAdapter); | ||
2321 | BusLogic_ReleaseResources(HostAdapter); | ||
2322 | list_del(&HostAdapter->host_list); | ||
2323 | scsi_host_put(Host); | ||
2324 | ret = -ENODEV; | ||
2325 | } else { | ||
2326 | scsi_scan_host(Host); | ||
2327 | BusLogicHostAdapterCount++; | ||
2328 | } | ||
2304 | } | 2329 | } |
2305 | } else { | 2330 | } else { |
2306 | /* | 2331 | /* |
@@ -2315,12 +2340,13 @@ static int __init BusLogic_init(void) | |||
2315 | BusLogic_ReleaseResources(HostAdapter); | 2340 | BusLogic_ReleaseResources(HostAdapter); |
2316 | list_del(&HostAdapter->host_list); | 2341 | list_del(&HostAdapter->host_list); |
2317 | scsi_host_put(Host); | 2342 | scsi_host_put(Host); |
2343 | ret = -ENODEV; | ||
2318 | } | 2344 | } |
2319 | } | 2345 | } |
2320 | kfree(PrototypeHostAdapter); | 2346 | kfree(PrototypeHostAdapter); |
2321 | kfree(BusLogic_ProbeInfoList); | 2347 | kfree(BusLogic_ProbeInfoList); |
2322 | BusLogic_ProbeInfoList = NULL; | 2348 | BusLogic_ProbeInfoList = NULL; |
2323 | return 0; | 2349 | return ret; |
2324 | } | 2350 | } |
2325 | 2351 | ||
2326 | 2352 | ||
@@ -2954,6 +2980,7 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou | |||
2954 | } | 2980 | } |
2955 | 2981 | ||
2956 | 2982 | ||
2983 | #if 0 | ||
2957 | /* | 2984 | /* |
2958 | BusLogic_AbortCommand aborts Command if possible. | 2985 | BusLogic_AbortCommand aborts Command if possible. |
2959 | */ | 2986 | */ |
@@ -3024,6 +3051,7 @@ static int BusLogic_AbortCommand(struct scsi_cmnd *Command) | |||
3024 | return SUCCESS; | 3051 | return SUCCESS; |
3025 | } | 3052 | } |
3026 | 3053 | ||
3054 | #endif | ||
3027 | /* | 3055 | /* |
3028 | BusLogic_ResetHostAdapter resets Host Adapter if possible, marking all | 3056 | BusLogic_ResetHostAdapter resets Host Adapter if possible, marking all |
3029 | currently executing SCSI Commands as having been Reset. | 3057 | currently executing SCSI Commands as having been Reset. |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 96a81cd1761..d61662c1a0e 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -469,6 +469,20 @@ config SCSI_IN2000 | |||
469 | To compile this driver as a module, choose M here: the | 469 | To compile this driver as a module, choose M here: the |
470 | module will be called in2000. | 470 | module will be called in2000. |
471 | 471 | ||
472 | config SCSI_ARCMSR | ||
473 | tristate "ARECA ARC11X0[PCI-X]/ARC12X0[PCI-EXPRESS] SATA-RAID support" | ||
474 | depends on PCI && SCSI | ||
475 | help | ||
476 | This driver supports all of ARECA's SATA RAID controller cards. | ||
477 | This is an ARECA-maintained driver by Erich Chen. | ||
478 | If you have any problems, please mail to: < erich@areca.com.tw > | ||
479 | Areca supports Linux RAID config tools. | ||
480 | |||
481 | < http://www.areca.com.tw > | ||
482 | |||
483 | To compile this driver as a module, choose M here: the | ||
484 | module will be called arcmsr (modprobe arcmsr). | ||
485 | |||
472 | source "drivers/scsi/megaraid/Kconfig.megaraid" | 486 | source "drivers/scsi/megaraid/Kconfig.megaraid" |
473 | 487 | ||
474 | config SCSI_SATA | 488 | config SCSI_SATA |
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index ebd0cf00bf3..b2de9bfdfdc 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
@@ -59,6 +59,7 @@ obj-$(CONFIG_SCSI_PSI240I) += psi240i.o | |||
59 | obj-$(CONFIG_SCSI_BUSLOGIC) += BusLogic.o | 59 | obj-$(CONFIG_SCSI_BUSLOGIC) += BusLogic.o |
60 | obj-$(CONFIG_SCSI_DPT_I2O) += dpt_i2o.o | 60 | obj-$(CONFIG_SCSI_DPT_I2O) += dpt_i2o.o |
61 | obj-$(CONFIG_SCSI_U14_34F) += u14-34f.o | 61 | obj-$(CONFIG_SCSI_U14_34F) += u14-34f.o |
62 | obj-$(CONFIG_SCSI_ARCMSR) += arcmsr/ | ||
62 | obj-$(CONFIG_SCSI_ULTRASTOR) += ultrastor.o | 63 | obj-$(CONFIG_SCSI_ULTRASTOR) += ultrastor.o |
63 | obj-$(CONFIG_SCSI_AHA152X) += aha152x.o | 64 | obj-$(CONFIG_SCSI_AHA152X) += aha152x.o |
64 | obj-$(CONFIG_SCSI_AHA1542) += aha1542.o | 65 | obj-$(CONFIG_SCSI_AHA1542) += aha1542.o |
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 83b5c7d085f..37c55ddce21 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
@@ -175,7 +175,7 @@ MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. | |||
175 | * | 175 | * |
176 | * Query config status, and commit the configuration if needed. | 176 | * Query config status, and commit the configuration if needed. |
177 | */ | 177 | */ |
178 | int aac_get_config_status(struct aac_dev *dev) | 178 | int aac_get_config_status(struct aac_dev *dev, int commit_flag) |
179 | { | 179 | { |
180 | int status = 0; | 180 | int status = 0; |
181 | struct fib * fibptr; | 181 | struct fib * fibptr; |
@@ -219,7 +219,7 @@ int aac_get_config_status(struct aac_dev *dev) | |||
219 | aac_fib_complete(fibptr); | 219 | aac_fib_complete(fibptr); |
220 | /* Send a CT_COMMIT_CONFIG to enable discovery of devices */ | 220 | /* Send a CT_COMMIT_CONFIG to enable discovery of devices */ |
221 | if (status >= 0) { | 221 | if (status >= 0) { |
222 | if (commit == 1) { | 222 | if ((commit == 1) || commit_flag) { |
223 | struct aac_commit_config * dinfo; | 223 | struct aac_commit_config * dinfo; |
224 | aac_fib_init(fibptr); | 224 | aac_fib_init(fibptr); |
225 | dinfo = (struct aac_commit_config *) fib_data(fibptr); | 225 | dinfo = (struct aac_commit_config *) fib_data(fibptr); |
@@ -489,6 +489,8 @@ int aac_probe_container(struct aac_dev *dev, int cid) | |||
489 | unsigned instance; | 489 | unsigned instance; |
490 | 490 | ||
491 | fsa_dev_ptr = dev->fsa_dev; | 491 | fsa_dev_ptr = dev->fsa_dev; |
492 | if (!fsa_dev_ptr) | ||
493 | return -ENOMEM; | ||
492 | instance = dev->scsi_host_ptr->unique_id; | 494 | instance = dev->scsi_host_ptr->unique_id; |
493 | 495 | ||
494 | if (!(fibptr = aac_fib_alloc(dev))) | 496 | if (!(fibptr = aac_fib_alloc(dev))) |
@@ -782,8 +784,9 @@ int aac_get_adapter_info(struct aac_dev* dev) | |||
782 | dev->maximum_num_channels = le32_to_cpu(bus_info->BusCount); | 784 | dev->maximum_num_channels = le32_to_cpu(bus_info->BusCount); |
783 | } | 785 | } |
784 | 786 | ||
785 | tmp = le32_to_cpu(dev->adapter_info.kernelrev); | 787 | if (!dev->in_reset) { |
786 | printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n", | 788 | tmp = le32_to_cpu(dev->adapter_info.kernelrev); |
789 | printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n", | ||
787 | dev->name, | 790 | dev->name, |
788 | dev->id, | 791 | dev->id, |
789 | tmp>>24, | 792 | tmp>>24, |
@@ -792,20 +795,21 @@ int aac_get_adapter_info(struct aac_dev* dev) | |||
792 | le32_to_cpu(dev->adapter_info.kernelbuild), | 795 | le32_to_cpu(dev->adapter_info.kernelbuild), |
793 | (int)sizeof(dev->supplement_adapter_info.BuildDate), | 796 | (int)sizeof(dev->supplement_adapter_info.BuildDate), |
794 | dev->supplement_adapter_info.BuildDate); | 797 | dev->supplement_adapter_info.BuildDate); |
795 | tmp = le32_to_cpu(dev->adapter_info.monitorrev); | 798 | tmp = le32_to_cpu(dev->adapter_info.monitorrev); |
796 | printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n", | 799 | printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n", |
797 | dev->name, dev->id, | 800 | dev->name, dev->id, |
798 | tmp>>24,(tmp>>16)&0xff,tmp&0xff, | 801 | tmp>>24,(tmp>>16)&0xff,tmp&0xff, |
799 | le32_to_cpu(dev->adapter_info.monitorbuild)); | 802 | le32_to_cpu(dev->adapter_info.monitorbuild)); |
800 | tmp = le32_to_cpu(dev->adapter_info.biosrev); | 803 | tmp = le32_to_cpu(dev->adapter_info.biosrev); |
801 | printk(KERN_INFO "%s%d: bios %d.%d-%d[%d]\n", | 804 | printk(KERN_INFO "%s%d: bios %d.%d-%d[%d]\n", |
802 | dev->name, dev->id, | 805 | dev->name, dev->id, |
803 | tmp>>24,(tmp>>16)&0xff,tmp&0xff, | 806 | tmp>>24,(tmp>>16)&0xff,tmp&0xff, |
804 | le32_to_cpu(dev->adapter_info.biosbuild)); | 807 | le32_to_cpu(dev->adapter_info.biosbuild)); |
805 | if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0) | 808 | if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0) |
806 | printk(KERN_INFO "%s%d: serial %x\n", | 809 | printk(KERN_INFO "%s%d: serial %x\n", |
807 | dev->name, dev->id, | 810 | dev->name, dev->id, |
808 | le32_to_cpu(dev->adapter_info.serial[0])); | 811 | le32_to_cpu(dev->adapter_info.serial[0])); |
812 | } | ||
809 | 813 | ||
810 | dev->nondasd_support = 0; | 814 | dev->nondasd_support = 0; |
811 | dev->raid_scsi_mode = 0; | 815 | dev->raid_scsi_mode = 0; |
@@ -1392,6 +1396,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid) | |||
1392 | struct scsi_cmnd *cmd; | 1396 | struct scsi_cmnd *cmd; |
1393 | struct scsi_device *sdev = scsicmd->device; | 1397 | struct scsi_device *sdev = scsicmd->device; |
1394 | int active = 0; | 1398 | int active = 0; |
1399 | struct aac_dev *aac; | ||
1395 | unsigned long flags; | 1400 | unsigned long flags; |
1396 | 1401 | ||
1397 | /* | 1402 | /* |
@@ -1413,11 +1418,14 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid) | |||
1413 | if (active) | 1418 | if (active) |
1414 | return SCSI_MLQUEUE_DEVICE_BUSY; | 1419 | return SCSI_MLQUEUE_DEVICE_BUSY; |
1415 | 1420 | ||
1421 | aac = (struct aac_dev *)scsicmd->device->host->hostdata; | ||
1422 | if (aac->in_reset) | ||
1423 | return SCSI_MLQUEUE_HOST_BUSY; | ||
1424 | |||
1416 | /* | 1425 | /* |
1417 | * Allocate and initialize a Fib | 1426 | * Allocate and initialize a Fib |
1418 | */ | 1427 | */ |
1419 | if (!(cmd_fibcontext = | 1428 | if (!(cmd_fibcontext = aac_fib_alloc(aac))) |
1420 | aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) | ||
1421 | return SCSI_MLQUEUE_HOST_BUSY; | 1429 | return SCSI_MLQUEUE_HOST_BUSY; |
1422 | 1430 | ||
1423 | aac_fib_init(cmd_fibcontext); | 1431 | aac_fib_init(cmd_fibcontext); |
@@ -1470,6 +1478,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1470 | struct aac_dev *dev = (struct aac_dev *)host->hostdata; | 1478 | struct aac_dev *dev = (struct aac_dev *)host->hostdata; |
1471 | struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev; | 1479 | struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev; |
1472 | 1480 | ||
1481 | if (fsa_dev_ptr == NULL) | ||
1482 | return -1; | ||
1473 | /* | 1483 | /* |
1474 | * If the bus, id or lun is out of range, return fail | 1484 | * If the bus, id or lun is out of range, return fail |
1475 | * Test does not apply to ID 16, the pseudo id for the controller | 1485 | * Test does not apply to ID 16, the pseudo id for the controller |
@@ -1499,6 +1509,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1499 | case INQUIRY: | 1509 | case INQUIRY: |
1500 | case READ_CAPACITY: | 1510 | case READ_CAPACITY: |
1501 | case TEST_UNIT_READY: | 1511 | case TEST_UNIT_READY: |
1512 | if (dev->in_reset) | ||
1513 | return -1; | ||
1502 | spin_unlock_irq(host->host_lock); | 1514 | spin_unlock_irq(host->host_lock); |
1503 | aac_probe_container(dev, cid); | 1515 | aac_probe_container(dev, cid); |
1504 | if ((fsa_dev_ptr[cid].valid & 1) == 0) | 1516 | if ((fsa_dev_ptr[cid].valid & 1) == 0) |
@@ -1524,6 +1536,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1524 | } | 1536 | } |
1525 | } else { /* check for physical non-dasd devices */ | 1537 | } else { /* check for physical non-dasd devices */ |
1526 | if(dev->nondasd_support == 1){ | 1538 | if(dev->nondasd_support == 1){ |
1539 | if (dev->in_reset) | ||
1540 | return -1; | ||
1527 | return aac_send_srb_fib(scsicmd); | 1541 | return aac_send_srb_fib(scsicmd); |
1528 | } else { | 1542 | } else { |
1529 | scsicmd->result = DID_NO_CONNECT << 16; | 1543 | scsicmd->result = DID_NO_CONNECT << 16; |
@@ -1579,6 +1593,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1579 | scsicmd->scsi_done(scsicmd); | 1593 | scsicmd->scsi_done(scsicmd); |
1580 | return 0; | 1594 | return 0; |
1581 | } | 1595 | } |
1596 | if (dev->in_reset) | ||
1597 | return -1; | ||
1582 | setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type); | 1598 | setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type); |
1583 | inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ | 1599 | inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ |
1584 | aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); | 1600 | aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); |
@@ -1734,6 +1750,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1734 | case READ_10: | 1750 | case READ_10: |
1735 | case READ_12: | 1751 | case READ_12: |
1736 | case READ_16: | 1752 | case READ_16: |
1753 | if (dev->in_reset) | ||
1754 | return -1; | ||
1737 | /* | 1755 | /* |
1738 | * Hack to keep track of ordinal number of the device that | 1756 | * Hack to keep track of ordinal number of the device that |
1739 | * corresponds to a container. Needed to convert | 1757 | * corresponds to a container. Needed to convert |
@@ -1752,6 +1770,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1752 | case WRITE_10: | 1770 | case WRITE_10: |
1753 | case WRITE_12: | 1771 | case WRITE_12: |
1754 | case WRITE_16: | 1772 | case WRITE_16: |
1773 | if (dev->in_reset) | ||
1774 | return -1; | ||
1755 | return aac_write(scsicmd, cid); | 1775 | return aac_write(scsicmd, cid); |
1756 | 1776 | ||
1757 | case SYNCHRONIZE_CACHE: | 1777 | case SYNCHRONIZE_CACHE: |
@@ -1782,6 +1802,8 @@ static int query_disk(struct aac_dev *dev, void __user *arg) | |||
1782 | struct fsa_dev_info *fsa_dev_ptr; | 1802 | struct fsa_dev_info *fsa_dev_ptr; |
1783 | 1803 | ||
1784 | fsa_dev_ptr = dev->fsa_dev; | 1804 | fsa_dev_ptr = dev->fsa_dev; |
1805 | if (!fsa_dev_ptr) | ||
1806 | return -ENODEV; | ||
1785 | if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk))) | 1807 | if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk))) |
1786 | return -EFAULT; | 1808 | return -EFAULT; |
1787 | if (qd.cnum == -1) | 1809 | if (qd.cnum == -1) |
@@ -1843,6 +1865,10 @@ static int delete_disk(struct aac_dev *dev, void __user *arg) | |||
1843 | struct fsa_dev_info *fsa_dev_ptr; | 1865 | struct fsa_dev_info *fsa_dev_ptr; |
1844 | 1866 | ||
1845 | fsa_dev_ptr = dev->fsa_dev; | 1867 | fsa_dev_ptr = dev->fsa_dev; |
1868 | if (!fsa_dev_ptr) | ||
1869 | return -ENODEV; | ||
1870 | if (!fsa_dev_ptr) | ||
1871 | return -ENODEV; | ||
1846 | 1872 | ||
1847 | if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk))) | 1873 | if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk))) |
1848 | return -EFAULT; | 1874 | return -EFAULT; |
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index d0eecd4bec8..8924c183d9c 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h | |||
@@ -1029,6 +1029,7 @@ struct aac_dev | |||
1029 | init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4) | 1029 | init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4) |
1030 | u8 raw_io_64; | 1030 | u8 raw_io_64; |
1031 | u8 printf_enabled; | 1031 | u8 printf_enabled; |
1032 | u8 in_reset; | ||
1032 | }; | 1033 | }; |
1033 | 1034 | ||
1034 | #define aac_adapter_interrupt(dev) \ | 1035 | #define aac_adapter_interrupt(dev) \ |
@@ -1670,6 +1671,7 @@ extern struct aac_common aac_config; | |||
1670 | #define RCV_TEMP_READINGS 0x00000025 | 1671 | #define RCV_TEMP_READINGS 0x00000025 |
1671 | #define GET_COMM_PREFERRED_SETTINGS 0x00000026 | 1672 | #define GET_COMM_PREFERRED_SETTINGS 0x00000026 |
1672 | #define IOP_RESET 0x00001000 | 1673 | #define IOP_RESET 0x00001000 |
1674 | #define IOP_RESET_ALWAYS 0x00001001 | ||
1673 | #define RE_INIT_ADAPTER 0x000000ee | 1675 | #define RE_INIT_ADAPTER 0x000000ee |
1674 | 1676 | ||
1675 | /* | 1677 | /* |
@@ -1788,7 +1790,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum); | |||
1788 | int aac_fib_complete(struct fib * context); | 1790 | int aac_fib_complete(struct fib * context); |
1789 | #define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data) | 1791 | #define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data) |
1790 | struct aac_dev *aac_init_adapter(struct aac_dev *dev); | 1792 | struct aac_dev *aac_init_adapter(struct aac_dev *dev); |
1791 | int aac_get_config_status(struct aac_dev *dev); | 1793 | int aac_get_config_status(struct aac_dev *dev, int commit_flag); |
1792 | int aac_get_containers(struct aac_dev *dev); | 1794 | int aac_get_containers(struct aac_dev *dev); |
1793 | int aac_scsi_cmd(struct scsi_cmnd *cmd); | 1795 | int aac_scsi_cmd(struct scsi_cmnd *cmd); |
1794 | int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg); | 1796 | int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg); |
@@ -1799,6 +1801,7 @@ int aac_sa_init(struct aac_dev *dev); | |||
1799 | unsigned int aac_response_normal(struct aac_queue * q); | 1801 | unsigned int aac_response_normal(struct aac_queue * q); |
1800 | unsigned int aac_command_normal(struct aac_queue * q); | 1802 | unsigned int aac_command_normal(struct aac_queue * q); |
1801 | unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index); | 1803 | unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index); |
1804 | int aac_check_health(struct aac_dev * dev); | ||
1802 | int aac_command_thread(void *data); | 1805 | int aac_command_thread(void *data); |
1803 | int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx); | 1806 | int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx); |
1804 | int aac_fib_adapter_complete(struct fib * fibptr, unsigned short size); | 1807 | int aac_fib_adapter_complete(struct fib * fibptr, unsigned short size); |
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 255421de9d1..da1d3a9212f 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include <linux/completion.h> | 38 | #include <linux/completion.h> |
39 | #include <linux/dma-mapping.h> | 39 | #include <linux/dma-mapping.h> |
40 | #include <linux/blkdev.h> | 40 | #include <linux/blkdev.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> /* ssleep prototype */ |
42 | #include <linux/kthread.h> | 42 | #include <linux/kthread.h> |
43 | #include <asm/semaphore.h> | 43 | #include <asm/semaphore.h> |
44 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
@@ -140,7 +140,8 @@ cleanup: | |||
140 | fibptr->hw_fib_pa = hw_fib_pa; | 140 | fibptr->hw_fib_pa = hw_fib_pa; |
141 | fibptr->hw_fib = hw_fib; | 141 | fibptr->hw_fib = hw_fib; |
142 | } | 142 | } |
143 | aac_fib_free(fibptr); | 143 | if (retval != -EINTR) |
144 | aac_fib_free(fibptr); | ||
144 | return retval; | 145 | return retval; |
145 | } | 146 | } |
146 | 147 | ||
@@ -297,7 +298,7 @@ return_fib: | |||
297 | spin_unlock_irqrestore(&dev->fib_lock, flags); | 298 | spin_unlock_irqrestore(&dev->fib_lock, flags); |
298 | /* If someone killed the AIF aacraid thread, restart it */ | 299 | /* If someone killed the AIF aacraid thread, restart it */ |
299 | status = !dev->aif_thread; | 300 | status = !dev->aif_thread; |
300 | if (status && dev->queues && dev->fsa_dev) { | 301 | if (status && !dev->in_reset && dev->queues && dev->fsa_dev) { |
301 | /* Be paranoid, be very paranoid! */ | 302 | /* Be paranoid, be very paranoid! */ |
302 | kthread_stop(dev->thread); | 303 | kthread_stop(dev->thread); |
303 | ssleep(1); | 304 | ssleep(1); |
@@ -621,7 +622,13 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) | |||
621 | 622 | ||
622 | actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry)); | 623 | actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry)); |
623 | if(actual_fibsize != fibsize){ // User made a mistake - should not continue | 624 | if(actual_fibsize != fibsize){ // User made a mistake - should not continue |
624 | dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n")); | 625 | dprintk((KERN_DEBUG"aacraid: Bad Size specified in " |
626 | "Raw SRB command calculated fibsize=%d " | ||
627 | "user_srbcmd->sg.count=%d aac_srb=%d sgentry=%d " | ||
628 | "issued fibsize=%d\n", | ||
629 | actual_fibsize, user_srbcmd->sg.count, | ||
630 | sizeof(struct aac_srb), sizeof(struct sgentry), | ||
631 | fibsize)); | ||
625 | rcode = -EINVAL; | 632 | rcode = -EINVAL; |
626 | goto cleanup; | 633 | goto cleanup; |
627 | } | 634 | } |
@@ -663,6 +670,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) | |||
663 | psg->count = cpu_to_le32(sg_indx+1); | 670 | psg->count = cpu_to_le32(sg_indx+1); |
664 | status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); | 671 | status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); |
665 | } | 672 | } |
673 | if (status == -EINTR) { | ||
674 | rcode = -EINTR; | ||
675 | goto cleanup; | ||
676 | } | ||
666 | 677 | ||
667 | if (status != 0){ | 678 | if (status != 0){ |
668 | dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n")); | 679 | dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n")); |
@@ -696,8 +707,10 @@ cleanup: | |||
696 | for(i=0; i <= sg_indx; i++){ | 707 | for(i=0; i <= sg_indx; i++){ |
697 | kfree(sg_list[i]); | 708 | kfree(sg_list[i]); |
698 | } | 709 | } |
699 | aac_fib_complete(srbfib); | 710 | if (rcode != -EINTR) { |
700 | aac_fib_free(srbfib); | 711 | aac_fib_complete(srbfib); |
712 | aac_fib_free(srbfib); | ||
713 | } | ||
701 | 714 | ||
702 | return rcode; | 715 | return rcode; |
703 | } | 716 | } |
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 1cd3584ba7f..87a95509676 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c | |||
@@ -180,7 +180,7 @@ int aac_send_shutdown(struct aac_dev * dev) | |||
180 | -2 /* Timeout silently */, 1, | 180 | -2 /* Timeout silently */, 1, |
181 | NULL, NULL); | 181 | NULL, NULL); |
182 | 182 | ||
183 | if (status == 0) | 183 | if (status >= 0) |
184 | aac_fib_complete(fibctx); | 184 | aac_fib_complete(fibctx); |
185 | aac_fib_free(fibctx); | 185 | aac_fib_free(fibctx); |
186 | return status; | 186 | return status; |
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 3f27419c66a..53add53be0b 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
@@ -40,8 +40,10 @@ | |||
40 | #include <linux/blkdev.h> | 40 | #include <linux/blkdev.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <linux/kthread.h> | 42 | #include <linux/kthread.h> |
43 | #include <scsi/scsi.h> | ||
43 | #include <scsi/scsi_host.h> | 44 | #include <scsi/scsi_host.h> |
44 | #include <scsi/scsi_device.h> | 45 | #include <scsi/scsi_device.h> |
46 | #include <scsi/scsi_cmnd.h> | ||
45 | #include <asm/semaphore.h> | 47 | #include <asm/semaphore.h> |
46 | 48 | ||
47 | #include "aacraid.h" | 49 | #include "aacraid.h" |
@@ -464,6 +466,8 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, | |||
464 | dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); | 466 | dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); |
465 | dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); | 467 | dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); |
466 | 468 | ||
469 | if (!dev->queues) | ||
470 | return -ENODEV; | ||
467 | q = &dev->queues->queue[AdapNormCmdQueue]; | 471 | q = &dev->queues->queue[AdapNormCmdQueue]; |
468 | 472 | ||
469 | if(wait) | 473 | if(wait) |
@@ -527,8 +531,15 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, | |||
527 | } | 531 | } |
528 | udelay(5); | 532 | udelay(5); |
529 | } | 533 | } |
530 | } else | 534 | } else if (down_interruptible(&fibptr->event_wait)) { |
531 | down(&fibptr->event_wait); | 535 | spin_lock_irqsave(&fibptr->event_lock, flags); |
536 | if (fibptr->done == 0) { | ||
537 | fibptr->done = 2; /* Tell interrupt we aborted */ | ||
538 | spin_unlock_irqrestore(&fibptr->event_lock, flags); | ||
539 | return -EINTR; | ||
540 | } | ||
541 | spin_unlock_irqrestore(&fibptr->event_lock, flags); | ||
542 | } | ||
532 | BUG_ON(fibptr->done == 0); | 543 | BUG_ON(fibptr->done == 0); |
533 | 544 | ||
534 | if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){ | 545 | if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){ |
@@ -795,7 +806,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | |||
795 | 806 | ||
796 | /* Sniff for container changes */ | 807 | /* Sniff for container changes */ |
797 | 808 | ||
798 | if (!dev) | 809 | if (!dev || !dev->fsa_dev) |
799 | return; | 810 | return; |
800 | container = (u32)-1; | 811 | container = (u32)-1; |
801 | 812 | ||
@@ -1045,6 +1056,262 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | |||
1045 | 1056 | ||
1046 | } | 1057 | } |
1047 | 1058 | ||
1059 | static int _aac_reset_adapter(struct aac_dev *aac) | ||
1060 | { | ||
1061 | int index, quirks; | ||
1062 | u32 ret; | ||
1063 | int retval; | ||
1064 | struct Scsi_Host *host; | ||
1065 | struct scsi_device *dev; | ||
1066 | struct scsi_cmnd *command; | ||
1067 | struct scsi_cmnd *command_list; | ||
1068 | |||
1069 | /* | ||
1070 | * Assumptions: | ||
1071 | * - host is locked. | ||
1072 | * - in_reset is asserted, so no new i/o is getting to the | ||
1073 | * card. | ||
1074 | * - The card is dead. | ||
1075 | */ | ||
1076 | host = aac->scsi_host_ptr; | ||
1077 | scsi_block_requests(host); | ||
1078 | aac_adapter_disable_int(aac); | ||
1079 | spin_unlock_irq(host->host_lock); | ||
1080 | kthread_stop(aac->thread); | ||
1081 | |||
1082 | /* | ||
1083 | * If a positive health, means in a known DEAD PANIC | ||
1084 | * state and the adapter could be reset to `try again'. | ||
1085 | */ | ||
1086 | retval = aac_adapter_check_health(aac); | ||
1087 | if (retval == 0) | ||
1088 | retval = aac_adapter_sync_cmd(aac, IOP_RESET_ALWAYS, | ||
1089 | 0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL); | ||
1090 | if (retval) | ||
1091 | retval = aac_adapter_sync_cmd(aac, IOP_RESET, | ||
1092 | 0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL); | ||
1093 | |||
1094 | if (retval) | ||
1095 | goto out; | ||
1096 | if (ret != 0x00000001) { | ||
1097 | retval = -ENODEV; | ||
1098 | goto out; | ||
1099 | } | ||
1100 | |||
1101 | index = aac->cardtype; | ||
1102 | |||
1103 | /* | ||
1104 | * Re-initialize the adapter, first free resources, then carefully | ||
1105 | * apply the initialization sequence to come back again. Only risk | ||
1106 | * is a change in Firmware dropping cache, it is assumed the caller | ||
1107 | * will ensure that i/o is queisced and the card is flushed in that | ||
1108 | * case. | ||
1109 | */ | ||
1110 | aac_fib_map_free(aac); | ||
1111 | aac->hw_fib_va = NULL; | ||
1112 | aac->hw_fib_pa = 0; | ||
1113 | pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); | ||
1114 | aac->comm_addr = NULL; | ||
1115 | aac->comm_phys = 0; | ||
1116 | kfree(aac->queues); | ||
1117 | aac->queues = NULL; | ||
1118 | free_irq(aac->pdev->irq, aac); | ||
1119 | kfree(aac->fsa_dev); | ||
1120 | aac->fsa_dev = NULL; | ||
1121 | if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT) { | ||
1122 | if (((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) || | ||
1123 | ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_32BIT_MASK)))) | ||
1124 | goto out; | ||
1125 | } else { | ||
1126 | if (((retval = pci_set_dma_mask(aac->pdev, 0x7FFFFFFFULL))) || | ||
1127 | ((retval = pci_set_consistent_dma_mask(aac->pdev, 0x7FFFFFFFULL)))) | ||
1128 | goto out; | ||
1129 | } | ||
1130 | if ((retval = (*(aac_get_driver_ident(index)->init))(aac))) | ||
1131 | goto out; | ||
1132 | if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT) | ||
1133 | if ((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) | ||
1134 | goto out; | ||
1135 | aac->thread = kthread_run(aac_command_thread, aac, aac->name); | ||
1136 | if (IS_ERR(aac->thread)) { | ||
1137 | retval = PTR_ERR(aac->thread); | ||
1138 | goto out; | ||
1139 | } | ||
1140 | (void)aac_get_adapter_info(aac); | ||
1141 | quirks = aac_get_driver_ident(index)->quirks; | ||
1142 | if ((quirks & AAC_QUIRK_34SG) && (host->sg_tablesize > 34)) { | ||
1143 | host->sg_tablesize = 34; | ||
1144 | host->max_sectors = (host->sg_tablesize * 8) + 112; | ||
1145 | } | ||
1146 | if ((quirks & AAC_QUIRK_17SG) && (host->sg_tablesize > 17)) { | ||
1147 | host->sg_tablesize = 17; | ||
1148 | host->max_sectors = (host->sg_tablesize * 8) + 112; | ||
1149 | } | ||
1150 | aac_get_config_status(aac, 1); | ||
1151 | aac_get_containers(aac); | ||
1152 | /* | ||
1153 | * This is where the assumption that the Adapter is quiesced | ||
1154 | * is important. | ||
1155 | */ | ||
1156 | command_list = NULL; | ||
1157 | __shost_for_each_device(dev, host) { | ||
1158 | unsigned long flags; | ||
1159 | spin_lock_irqsave(&dev->list_lock, flags); | ||
1160 | list_for_each_entry(command, &dev->cmd_list, list) | ||
1161 | if (command->SCp.phase == AAC_OWNER_FIRMWARE) { | ||
1162 | command->SCp.buffer = (struct scatterlist *)command_list; | ||
1163 | command_list = command; | ||
1164 | } | ||
1165 | spin_unlock_irqrestore(&dev->list_lock, flags); | ||
1166 | } | ||
1167 | while ((command = command_list)) { | ||
1168 | command_list = (struct scsi_cmnd *)command->SCp.buffer; | ||
1169 | command->SCp.buffer = NULL; | ||
1170 | command->result = DID_OK << 16 | ||
1171 | | COMMAND_COMPLETE << 8 | ||
1172 | | SAM_STAT_TASK_SET_FULL; | ||
1173 | command->SCp.phase = AAC_OWNER_ERROR_HANDLER; | ||
1174 | command->scsi_done(command); | ||
1175 | } | ||
1176 | retval = 0; | ||
1177 | |||
1178 | out: | ||
1179 | aac->in_reset = 0; | ||
1180 | scsi_unblock_requests(host); | ||
1181 | spin_lock_irq(host->host_lock); | ||
1182 | return retval; | ||
1183 | } | ||
1184 | |||
1185 | int aac_check_health(struct aac_dev * aac) | ||
1186 | { | ||
1187 | int BlinkLED; | ||
1188 | unsigned long time_now, flagv = 0; | ||
1189 | struct list_head * entry; | ||
1190 | struct Scsi_Host * host; | ||
1191 | |||
1192 | /* Extending the scope of fib_lock slightly to protect aac->in_reset */ | ||
1193 | if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0) | ||
1194 | return 0; | ||
1195 | |||
1196 | if (aac->in_reset || !(BlinkLED = aac_adapter_check_health(aac))) { | ||
1197 | spin_unlock_irqrestore(&aac->fib_lock, flagv); | ||
1198 | return 0; /* OK */ | ||
1199 | } | ||
1200 | |||
1201 | aac->in_reset = 1; | ||
1202 | |||
1203 | /* Fake up an AIF: | ||
1204 | * aac_aifcmd.command = AifCmdEventNotify = 1 | ||
1205 | * aac_aifcmd.seqnum = 0xFFFFFFFF | ||
1206 | * aac_aifcmd.data[0] = AifEnExpEvent = 23 | ||
1207 | * aac_aifcmd.data[1] = AifExeFirmwarePanic = 3 | ||
1208 | * aac.aifcmd.data[2] = AifHighPriority = 3 | ||
1209 | * aac.aifcmd.data[3] = BlinkLED | ||
1210 | */ | ||
1211 | |||
1212 | time_now = jiffies/HZ; | ||
1213 | entry = aac->fib_list.next; | ||
1214 | |||
1215 | /* | ||
1216 | * For each Context that is on the | ||
1217 | * fibctxList, make a copy of the | ||
1218 | * fib, and then set the event to wake up the | ||
1219 | * thread that is waiting for it. | ||
1220 | */ | ||
1221 | while (entry != &aac->fib_list) { | ||
1222 | /* | ||
1223 | * Extract the fibctx | ||
1224 | */ | ||
1225 | struct aac_fib_context *fibctx = list_entry(entry, struct aac_fib_context, next); | ||
1226 | struct hw_fib * hw_fib; | ||
1227 | struct fib * fib; | ||
1228 | /* | ||
1229 | * Check if the queue is getting | ||
1230 | * backlogged | ||
1231 | */ | ||
1232 | if (fibctx->count > 20) { | ||
1233 | /* | ||
1234 | * It's *not* jiffies folks, | ||
1235 | * but jiffies / HZ, so do not | ||
1236 | * panic ... | ||
1237 | */ | ||
1238 | u32 time_last = fibctx->jiffies; | ||
1239 | /* | ||
1240 | * Has it been > 2 minutes | ||
1241 | * since the last read off | ||
1242 | * the queue? | ||
1243 | */ | ||
1244 | if ((time_now - time_last) > aif_timeout) { | ||
1245 | entry = entry->next; | ||
1246 | aac_close_fib_context(aac, fibctx); | ||
1247 | continue; | ||
1248 | } | ||
1249 | } | ||
1250 | /* | ||
1251 | * Warning: no sleep allowed while | ||
1252 | * holding spinlock | ||
1253 | */ | ||
1254 | hw_fib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); | ||
1255 | fib = kmalloc(sizeof(struct fib), GFP_ATOMIC); | ||
1256 | if (fib && hw_fib) { | ||
1257 | struct aac_aifcmd * aif; | ||
1258 | |||
1259 | memset(hw_fib, 0, sizeof(struct hw_fib)); | ||
1260 | memset(fib, 0, sizeof(struct fib)); | ||
1261 | fib->hw_fib = hw_fib; | ||
1262 | fib->dev = aac; | ||
1263 | aac_fib_init(fib); | ||
1264 | fib->type = FSAFS_NTC_FIB_CONTEXT; | ||
1265 | fib->size = sizeof (struct fib); | ||
1266 | fib->data = hw_fib->data; | ||
1267 | aif = (struct aac_aifcmd *)hw_fib->data; | ||
1268 | aif->command = cpu_to_le32(AifCmdEventNotify); | ||
1269 | aif->seqnum = cpu_to_le32(0xFFFFFFFF); | ||
1270 | aif->data[0] = cpu_to_le32(AifEnExpEvent); | ||
1271 | aif->data[1] = cpu_to_le32(AifExeFirmwarePanic); | ||
1272 | aif->data[2] = cpu_to_le32(AifHighPriority); | ||
1273 | aif->data[3] = cpu_to_le32(BlinkLED); | ||
1274 | |||
1275 | /* | ||
1276 | * Put the FIB onto the | ||
1277 | * fibctx's fibs | ||
1278 | */ | ||
1279 | list_add_tail(&fib->fiblink, &fibctx->fib_list); | ||
1280 | fibctx->count++; | ||
1281 | /* | ||
1282 | * Set the event to wake up the | ||
1283 | * thread that will waiting. | ||
1284 | */ | ||
1285 | up(&fibctx->wait_sem); | ||
1286 | } else { | ||
1287 | printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); | ||
1288 | kfree(fib); | ||
1289 | kfree(hw_fib); | ||
1290 | } | ||
1291 | entry = entry->next; | ||
1292 | } | ||
1293 | |||
1294 | spin_unlock_irqrestore(&aac->fib_lock, flagv); | ||
1295 | |||
1296 | if (BlinkLED < 0) { | ||
1297 | printk(KERN_ERR "%s: Host adapter dead %d\n", aac->name, BlinkLED); | ||
1298 | goto out; | ||
1299 | } | ||
1300 | |||
1301 | printk(KERN_ERR "%s: Host adapter BLINK LED 0x%x\n", aac->name, BlinkLED); | ||
1302 | |||
1303 | host = aac->scsi_host_ptr; | ||
1304 | spin_lock_irqsave(host->host_lock, flagv); | ||
1305 | BlinkLED = _aac_reset_adapter(aac); | ||
1306 | spin_unlock_irqrestore(host->host_lock, flagv); | ||
1307 | return BlinkLED; | ||
1308 | |||
1309 | out: | ||
1310 | aac->in_reset = 0; | ||
1311 | return BlinkLED; | ||
1312 | } | ||
1313 | |||
1314 | |||
1048 | /** | 1315 | /** |
1049 | * aac_command_thread - command processing thread | 1316 | * aac_command_thread - command processing thread |
1050 | * @dev: Adapter to monitor | 1317 | * @dev: Adapter to monitor |
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index b2a5c7262f3..8335f07b772 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c | |||
@@ -124,10 +124,15 @@ unsigned int aac_response_normal(struct aac_queue * q) | |||
124 | } else { | 124 | } else { |
125 | unsigned long flagv; | 125 | unsigned long flagv; |
126 | spin_lock_irqsave(&fib->event_lock, flagv); | 126 | spin_lock_irqsave(&fib->event_lock, flagv); |
127 | fib->done = 1; | 127 | if (!fib->done) |
128 | fib->done = 1; | ||
128 | up(&fib->event_wait); | 129 | up(&fib->event_wait); |
129 | spin_unlock_irqrestore(&fib->event_lock, flagv); | 130 | spin_unlock_irqrestore(&fib->event_lock, flagv); |
130 | FIB_COUNTER_INCREMENT(aac_config.NormalRecved); | 131 | FIB_COUNTER_INCREMENT(aac_config.NormalRecved); |
132 | if (fib->done == 2) { | ||
133 | aac_fib_complete(fib); | ||
134 | aac_fib_free(fib); | ||
135 | } | ||
131 | } | 136 | } |
132 | consumed++; | 137 | consumed++; |
133 | spin_lock_irqsave(q->lock, flags); | 138 | spin_lock_irqsave(q->lock, flags); |
@@ -316,7 +321,8 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index) | |||
316 | unsigned long flagv; | 321 | unsigned long flagv; |
317 | dprintk((KERN_INFO "event_wait up\n")); | 322 | dprintk((KERN_INFO "event_wait up\n")); |
318 | spin_lock_irqsave(&fib->event_lock, flagv); | 323 | spin_lock_irqsave(&fib->event_lock, flagv); |
319 | fib->done = 1; | 324 | if (!fib->done) |
325 | fib->done = 1; | ||
320 | up(&fib->event_wait); | 326 | up(&fib->event_wait); |
321 | spin_unlock_irqrestore(&fib->event_lock, flagv); | 327 | spin_unlock_irqrestore(&fib->event_lock, flagv); |
322 | FIB_COUNTER_INCREMENT(aac_config.NormalRecved); | 328 | FIB_COUNTER_INCREMENT(aac_config.NormalRecved); |
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index e42a479ce64..d67058f8081 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
@@ -454,17 +454,17 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) | |||
454 | printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", | 454 | printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", |
455 | AAC_DRIVERNAME); | 455 | AAC_DRIVERNAME); |
456 | aac = (struct aac_dev *)host->hostdata; | 456 | aac = (struct aac_dev *)host->hostdata; |
457 | if (aac_adapter_check_health(aac)) { | 457 | |
458 | printk(KERN_ERR "%s: Host adapter appears dead\n", | 458 | if ((count = aac_check_health(aac))) |
459 | AAC_DRIVERNAME); | 459 | return count; |
460 | return -ENODEV; | ||
461 | } | ||
462 | /* | 460 | /* |
463 | * Wait for all commands to complete to this specific | 461 | * Wait for all commands to complete to this specific |
464 | * target (block maximum 60 seconds). | 462 | * target (block maximum 60 seconds). |
465 | */ | 463 | */ |
466 | for (count = 60; count; --count) { | 464 | for (count = 60; count; --count) { |
467 | int active = 0; | 465 | int active = aac->in_reset; |
466 | |||
467 | if (active == 0) | ||
468 | __shost_for_each_device(dev, host) { | 468 | __shost_for_each_device(dev, host) { |
469 | spin_lock_irqsave(&dev->list_lock, flags); | 469 | spin_lock_irqsave(&dev->list_lock, flags); |
470 | list_for_each_entry(command, &dev->cmd_list, list) { | 470 | list_for_each_entry(command, &dev->cmd_list, list) { |
@@ -933,7 +933,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, | |||
933 | else | 933 | else |
934 | shost->max_channel = 0; | 934 | shost->max_channel = 0; |
935 | 935 | ||
936 | aac_get_config_status(aac); | 936 | aac_get_config_status(aac, 0); |
937 | aac_get_containers(aac); | 937 | aac_get_containers(aac); |
938 | list_add(&aac->entry, insert); | 938 | list_add(&aac->entry, insert); |
939 | 939 | ||
@@ -1013,6 +1013,10 @@ static void __devexit aac_remove_one(struct pci_dev *pdev) | |||
1013 | list_del(&aac->entry); | 1013 | list_del(&aac->entry); |
1014 | scsi_host_put(shost); | 1014 | scsi_host_put(shost); |
1015 | pci_disable_device(pdev); | 1015 | pci_disable_device(pdev); |
1016 | if (list_empty(&aac_devices)) { | ||
1017 | unregister_chrdev(aac_cfg_major, "aac"); | ||
1018 | aac_cfg_major = -1; | ||
1019 | } | ||
1016 | } | 1020 | } |
1017 | 1021 | ||
1018 | static struct pci_driver aac_pci_driver = { | 1022 | static struct pci_driver aac_pci_driver = { |
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index 458ea897fd7..f850c3a7cce 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c | |||
@@ -395,6 +395,25 @@ static int aac_rkt_send(struct fib * fib) | |||
395 | return 0; | 395 | return 0; |
396 | } | 396 | } |
397 | 397 | ||
398 | static int aac_rkt_restart_adapter(struct aac_dev *dev) | ||
399 | { | ||
400 | u32 var; | ||
401 | |||
402 | printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", | ||
403 | dev->name, dev->id); | ||
404 | |||
405 | if (aac_rkt_check_health(dev) <= 0) | ||
406 | return 1; | ||
407 | if (rkt_sync_cmd(dev, IOP_RESET, 0, 0, 0, 0, 0, 0, | ||
408 | &var, NULL, NULL, NULL, NULL)) | ||
409 | return 1; | ||
410 | if (var != 0x00000001) | ||
411 | return 1; | ||
412 | if (rkt_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) | ||
413 | return 1; | ||
414 | return 0; | ||
415 | } | ||
416 | |||
398 | /** | 417 | /** |
399 | * aac_rkt_init - initialize an i960 based AAC card | 418 | * aac_rkt_init - initialize an i960 based AAC card |
400 | * @dev: device to configure | 419 | * @dev: device to configure |
@@ -417,6 +436,9 @@ int aac_rkt_init(struct aac_dev *dev) | |||
417 | /* | 436 | /* |
418 | * Check to see if the board panic'd while booting. | 437 | * Check to see if the board panic'd while booting. |
419 | */ | 438 | */ |
439 | if (rkt_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) | ||
440 | if (aac_rkt_restart_adapter(dev)) | ||
441 | goto error_iounmap; | ||
420 | /* | 442 | /* |
421 | * Check to see if the board failed any self tests. | 443 | * Check to see if the board failed any self tests. |
422 | */ | 444 | */ |
@@ -431,13 +453,6 @@ int aac_rkt_init(struct aac_dev *dev) | |||
431 | printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance); | 453 | printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance); |
432 | goto error_iounmap; | 454 | goto error_iounmap; |
433 | } | 455 | } |
434 | /* | ||
435 | * Check to see if the board panic'd while booting. | ||
436 | */ | ||
437 | if (rkt_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) { | ||
438 | printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", dev->name, instance); | ||
439 | goto error_iounmap; | ||
440 | } | ||
441 | start = jiffies; | 456 | start = jiffies; |
442 | /* | 457 | /* |
443 | * Wait for the adapter to be up and running. Wait up to 3 minutes | 458 | * Wait for the adapter to be up and running. Wait up to 3 minutes |
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 035018db69b..c715c4b2442 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c | |||
@@ -394,6 +394,25 @@ static int aac_rx_send(struct fib * fib) | |||
394 | return 0; | 394 | return 0; |
395 | } | 395 | } |
396 | 396 | ||
397 | static int aac_rx_restart_adapter(struct aac_dev *dev) | ||
398 | { | ||
399 | u32 var; | ||
400 | |||
401 | printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", | ||
402 | dev->name, dev->id); | ||
403 | |||
404 | if (aac_rx_check_health(dev) <= 0) | ||
405 | return 1; | ||
406 | if (rx_sync_cmd(dev, IOP_RESET, 0, 0, 0, 0, 0, 0, | ||
407 | &var, NULL, NULL, NULL, NULL)) | ||
408 | return 1; | ||
409 | if (var != 0x00000001) | ||
410 | return 1; | ||
411 | if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) | ||
412 | return 1; | ||
413 | return 0; | ||
414 | } | ||
415 | |||
397 | /** | 416 | /** |
398 | * aac_rx_init - initialize an i960 based AAC card | 417 | * aac_rx_init - initialize an i960 based AAC card |
399 | * @dev: device to configure | 418 | * @dev: device to configure |
@@ -416,6 +435,9 @@ int aac_rx_init(struct aac_dev *dev) | |||
416 | /* | 435 | /* |
417 | * Check to see if the board panic'd while booting. | 436 | * Check to see if the board panic'd while booting. |
418 | */ | 437 | */ |
438 | if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) | ||
439 | if (aac_rx_restart_adapter(dev)) | ||
440 | goto error_iounmap; | ||
419 | /* | 441 | /* |
420 | * Check to see if the board failed any self tests. | 442 | * Check to see if the board failed any self tests. |
421 | */ | 443 | */ |
@@ -424,13 +446,6 @@ int aac_rx_init(struct aac_dev *dev) | |||
424 | goto error_iounmap; | 446 | goto error_iounmap; |
425 | } | 447 | } |
426 | /* | 448 | /* |
427 | * Check to see if the board panic'd while booting. | ||
428 | */ | ||
429 | if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) { | ||
430 | printk(KERN_ERR "%s%d: adapter kernel panic.\n", dev->name, instance); | ||
431 | goto error_iounmap; | ||
432 | } | ||
433 | /* | ||
434 | * Check to see if the monitor panic'd while booting. | 449 | * Check to see if the monitor panic'd while booting. |
435 | */ | 450 | */ |
436 | if (rx_readl(dev, MUnit.OMRx[0]) & MONITOR_PANIC) { | 451 | if (rx_readl(dev, MUnit.OMRx[0]) & MONITOR_PANIC) { |
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index e32b4ab2f8f..773f02e3b10 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c | |||
@@ -888,10 +888,6 @@ typedef unsigned char uchar; | |||
888 | #define ASC_PCI_ID2DEV(id) (((id) >> 11) & 0x1F) | 888 | #define ASC_PCI_ID2DEV(id) (((id) >> 11) & 0x1F) |
889 | #define ASC_PCI_ID2FUNC(id) (((id) >> 8) & 0x7) | 889 | #define ASC_PCI_ID2FUNC(id) (((id) >> 8) & 0x7) |
890 | #define ASC_PCI_MKID(bus, dev, func) ((((dev) & 0x1F) << 11) | (((func) & 0x7) << 8) | ((bus) & 0xFF)) | 890 | #define ASC_PCI_MKID(bus, dev, func) ((((dev) & 0x1F) << 11) | (((func) & 0x7) << 8) | ((bus) & 0xFF)) |
891 | #define ASC_PCI_VENDORID 0x10CD | ||
892 | #define ASC_PCI_DEVICEID_1200A 0x1100 | ||
893 | #define ASC_PCI_DEVICEID_1200B 0x1200 | ||
894 | #define ASC_PCI_DEVICEID_ULTRA 0x1300 | ||
895 | #define ASC_PCI_REVISION_3150 0x02 | 891 | #define ASC_PCI_REVISION_3150 0x02 |
896 | #define ASC_PCI_REVISION_3050 0x03 | 892 | #define ASC_PCI_REVISION_3050 0x03 |
897 | 893 | ||
@@ -899,6 +895,14 @@ typedef unsigned char uchar; | |||
899 | #define ASC_DVCLIB_CALL_FAILED (0) | 895 | #define ASC_DVCLIB_CALL_FAILED (0) |
900 | #define ASC_DVCLIB_CALL_ERROR (-1) | 896 | #define ASC_DVCLIB_CALL_ERROR (-1) |
901 | 897 | ||
898 | #define PCI_VENDOR_ID_ASP 0x10cd | ||
899 | #define PCI_DEVICE_ID_ASP_1200A 0x1100 | ||
900 | #define PCI_DEVICE_ID_ASP_ABP940 0x1200 | ||
901 | #define PCI_DEVICE_ID_ASP_ABP940U 0x1300 | ||
902 | #define PCI_DEVICE_ID_ASP_ABP940UW 0x2300 | ||
903 | #define PCI_DEVICE_ID_38C0800_REV1 0x2500 | ||
904 | #define PCI_DEVICE_ID_38C1600_REV1 0x2700 | ||
905 | |||
902 | /* | 906 | /* |
903 | * Enable CC_VERY_LONG_SG_LIST to support up to 64K element SG lists. | 907 | * Enable CC_VERY_LONG_SG_LIST to support up to 64K element SG lists. |
904 | * The SRB structure will have to be changed and the ASC_SRB2SCSIQ() | 908 | * The SRB structure will have to be changed and the ASC_SRB2SCSIQ() |
@@ -1492,8 +1496,6 @@ typedef struct asc_dvc_cfg { | |||
1492 | #define ASC_INIT_STATE_END_INQUIRY 0x0080 | 1496 | #define ASC_INIT_STATE_END_INQUIRY 0x0080 |
1493 | #define ASC_INIT_RESET_SCSI_DONE 0x0100 | 1497 | #define ASC_INIT_RESET_SCSI_DONE 0x0100 |
1494 | #define ASC_INIT_STATE_WITHOUT_EEP 0x8000 | 1498 | #define ASC_INIT_STATE_WITHOUT_EEP 0x8000 |
1495 | #define ASC_PCI_DEVICE_ID_REV_A 0x1100 | ||
1496 | #define ASC_PCI_DEVICE_ID_REV_B 0x1200 | ||
1497 | #define ASC_BUG_FIX_IF_NOT_DWB 0x0001 | 1499 | #define ASC_BUG_FIX_IF_NOT_DWB 0x0001 |
1498 | #define ASC_BUG_FIX_ASYN_USE_SYN 0x0002 | 1500 | #define ASC_BUG_FIX_ASYN_USE_SYN 0x0002 |
1499 | #define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41 | 1501 | #define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41 |
@@ -2100,12 +2102,6 @@ STATIC ASC_DCNT AscGetMaxDmaCount(ushort); | |||
2100 | #define ADV_NUM_PAGE_CROSSING \ | 2102 | #define ADV_NUM_PAGE_CROSSING \ |
2101 | ((ADV_SG_TOTAL_MEM_SIZE + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE) | 2103 | ((ADV_SG_TOTAL_MEM_SIZE + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE) |
2102 | 2104 | ||
2103 | /* a_condor.h */ | ||
2104 | #define ADV_PCI_VENDOR_ID 0x10CD | ||
2105 | #define ADV_PCI_DEVICE_ID_REV_A 0x2300 | ||
2106 | #define ADV_PCI_DEVID_38C0800_REV1 0x2500 | ||
2107 | #define ADV_PCI_DEVID_38C1600_REV1 0x2700 | ||
2108 | |||
2109 | #define ADV_EEP_DVC_CFG_BEGIN (0x00) | 2105 | #define ADV_EEP_DVC_CFG_BEGIN (0x00) |
2110 | #define ADV_EEP_DVC_CFG_END (0x15) | 2106 | #define ADV_EEP_DVC_CFG_END (0x15) |
2111 | #define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */ | 2107 | #define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */ |
@@ -3569,14 +3565,7 @@ typedef struct scsi_cmnd REQ, *REQP; | |||
3569 | #define PCI_MAX_SLOT 0x1F | 3565 | #define PCI_MAX_SLOT 0x1F |
3570 | #define PCI_MAX_BUS 0xFF | 3566 | #define PCI_MAX_BUS 0xFF |
3571 | #define PCI_IOADDRESS_MASK 0xFFFE | 3567 | #define PCI_IOADDRESS_MASK 0xFFFE |
3572 | #define ASC_PCI_VENDORID 0x10CD | ||
3573 | #define ASC_PCI_DEVICE_ID_CNT 6 /* PCI Device ID count. */ | 3568 | #define ASC_PCI_DEVICE_ID_CNT 6 /* PCI Device ID count. */ |
3574 | #define ASC_PCI_DEVICE_ID_1100 0x1100 | ||
3575 | #define ASC_PCI_DEVICE_ID_1200 0x1200 | ||
3576 | #define ASC_PCI_DEVICE_ID_1300 0x1300 | ||
3577 | #define ASC_PCI_DEVICE_ID_2300 0x2300 /* ASC-3550 */ | ||
3578 | #define ASC_PCI_DEVICE_ID_2500 0x2500 /* ASC-38C0800 */ | ||
3579 | #define ASC_PCI_DEVICE_ID_2700 0x2700 /* ASC-38C1600 */ | ||
3580 | 3569 | ||
3581 | #ifndef ADVANSYS_STATS | 3570 | #ifndef ADVANSYS_STATS |
3582 | #define ASC_STATS(shp, counter) | 3571 | #define ASC_STATS(shp, counter) |
@@ -4330,12 +4319,12 @@ advansys_detect(struct scsi_host_template *tpnt) | |||
4330 | struct pci_dev *pci_devp = NULL; | 4319 | struct pci_dev *pci_devp = NULL; |
4331 | int pci_device_id_cnt = 0; | 4320 | int pci_device_id_cnt = 0; |
4332 | unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = { | 4321 | unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = { |
4333 | ASC_PCI_DEVICE_ID_1100, | 4322 | PCI_DEVICE_ID_ASP_1200A, |
4334 | ASC_PCI_DEVICE_ID_1200, | 4323 | PCI_DEVICE_ID_ASP_ABP940, |
4335 | ASC_PCI_DEVICE_ID_1300, | 4324 | PCI_DEVICE_ID_ASP_ABP940U, |
4336 | ASC_PCI_DEVICE_ID_2300, | 4325 | PCI_DEVICE_ID_ASP_ABP940UW, |
4337 | ASC_PCI_DEVICE_ID_2500, | 4326 | PCI_DEVICE_ID_38C0800_REV1, |
4338 | ASC_PCI_DEVICE_ID_2700 | 4327 | PCI_DEVICE_ID_38C1600_REV1 |
4339 | }; | 4328 | }; |
4340 | ADV_PADDR pci_memory_address; | 4329 | ADV_PADDR pci_memory_address; |
4341 | #endif /* CONFIG_PCI */ | 4330 | #endif /* CONFIG_PCI */ |
@@ -4471,7 +4460,7 @@ advansys_detect(struct scsi_host_template *tpnt) | |||
4471 | 4460 | ||
4472 | /* Find all PCI cards. */ | 4461 | /* Find all PCI cards. */ |
4473 | while (pci_device_id_cnt < ASC_PCI_DEVICE_ID_CNT) { | 4462 | while (pci_device_id_cnt < ASC_PCI_DEVICE_ID_CNT) { |
4474 | if ((pci_devp = pci_find_device(ASC_PCI_VENDORID, | 4463 | if ((pci_devp = pci_find_device(PCI_VENDOR_ID_ASP, |
4475 | pci_device_id[pci_device_id_cnt], pci_devp)) == | 4464 | pci_device_id[pci_device_id_cnt], pci_devp)) == |
4476 | NULL) { | 4465 | NULL) { |
4477 | pci_device_id_cnt++; | 4466 | pci_device_id_cnt++; |
@@ -4575,9 +4564,9 @@ advansys_detect(struct scsi_host_template *tpnt) | |||
4575 | */ | 4564 | */ |
4576 | #ifdef CONFIG_PCI | 4565 | #ifdef CONFIG_PCI |
4577 | if (asc_bus[bus] == ASC_IS_PCI && | 4566 | if (asc_bus[bus] == ASC_IS_PCI && |
4578 | (pci_devp->device == ASC_PCI_DEVICE_ID_2300 || | 4567 | (pci_devp->device == PCI_DEVICE_ID_ASP_ABP940UW || |
4579 | pci_devp->device == ASC_PCI_DEVICE_ID_2500 || | 4568 | pci_devp->device == PCI_DEVICE_ID_38C0800_REV1 || |
4580 | pci_devp->device == ASC_PCI_DEVICE_ID_2700)) | 4569 | pci_devp->device == PCI_DEVICE_ID_38C1600_REV1)) |
4581 | { | 4570 | { |
4582 | boardp->flags |= ASC_IS_WIDE_BOARD; | 4571 | boardp->flags |= ASC_IS_WIDE_BOARD; |
4583 | } | 4572 | } |
@@ -4600,11 +4589,11 @@ advansys_detect(struct scsi_host_template *tpnt) | |||
4600 | adv_dvc_varp->isr_callback = adv_isr_callback; | 4589 | adv_dvc_varp->isr_callback = adv_isr_callback; |
4601 | adv_dvc_varp->async_callback = adv_async_callback; | 4590 | adv_dvc_varp->async_callback = adv_async_callback; |
4602 | #ifdef CONFIG_PCI | 4591 | #ifdef CONFIG_PCI |
4603 | if (pci_devp->device == ASC_PCI_DEVICE_ID_2300) | 4592 | if (pci_devp->device == PCI_DEVICE_ID_ASP_ABP940UW) |
4604 | { | 4593 | { |
4605 | ASC_DBG(1, "advansys_detect: ASC-3550\n"); | 4594 | ASC_DBG(1, "advansys_detect: ASC-3550\n"); |
4606 | adv_dvc_varp->chip_type = ADV_CHIP_ASC3550; | 4595 | adv_dvc_varp->chip_type = ADV_CHIP_ASC3550; |
4607 | } else if (pci_devp->device == ASC_PCI_DEVICE_ID_2500) | 4596 | } else if (pci_devp->device == PCI_DEVICE_ID_38C0800_REV1) |
4608 | { | 4597 | { |
4609 | ASC_DBG(1, "advansys_detect: ASC-38C0800\n"); | 4598 | ASC_DBG(1, "advansys_detect: ASC-38C0800\n"); |
4610 | adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800; | 4599 | adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800; |
@@ -11922,7 +11911,7 @@ AscInitGetConfig( | |||
11922 | PCIRevisionID = DvcReadPCIConfigByte(asc_dvc, | 11911 | PCIRevisionID = DvcReadPCIConfigByte(asc_dvc, |
11923 | AscPCIConfigRevisionIDRegister); | 11912 | AscPCIConfigRevisionIDRegister); |
11924 | 11913 | ||
11925 | if (PCIVendorID != ASC_PCI_VENDORID) { | 11914 | if (PCIVendorID != PCI_VENDOR_ID_ASP) { |
11926 | warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; | 11915 | warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; |
11927 | } | 11916 | } |
11928 | prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc, | 11917 | prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc, |
@@ -11942,15 +11931,15 @@ AscInitGetConfig( | |||
11942 | warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; | 11931 | warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; |
11943 | } | 11932 | } |
11944 | } | 11933 | } |
11945 | if ((PCIDeviceID == ASC_PCI_DEVICEID_1200A) || | 11934 | if ((PCIDeviceID == PCI_DEVICE_ID_ASP_1200A) || |
11946 | (PCIDeviceID == ASC_PCI_DEVICEID_1200B)) { | 11935 | (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940)) { |
11947 | DvcWritePCIConfigByte(asc_dvc, | 11936 | DvcWritePCIConfigByte(asc_dvc, |
11948 | AscPCIConfigLatencyTimer, 0x00); | 11937 | AscPCIConfigLatencyTimer, 0x00); |
11949 | if (DvcReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) | 11938 | if (DvcReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) |
11950 | != 0x00) { | 11939 | != 0x00) { |
11951 | warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; | 11940 | warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; |
11952 | } | 11941 | } |
11953 | } else if (PCIDeviceID == ASC_PCI_DEVICEID_ULTRA) { | 11942 | } else if (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940U) { |
11954 | if (DvcReadPCIConfigByte(asc_dvc, | 11943 | if (DvcReadPCIConfigByte(asc_dvc, |
11955 | AscPCIConfigLatencyTimer) < 0x20) { | 11944 | AscPCIConfigLatencyTimer) < 0x20) { |
11956 | DvcWritePCIConfigByte(asc_dvc, | 11945 | DvcWritePCIConfigByte(asc_dvc, |
@@ -12037,8 +12026,8 @@ AscInitFromAscDvcVar( | |||
12037 | AscSetChipCfgMsw(iop_base, cfg_msw); | 12026 | AscSetChipCfgMsw(iop_base, cfg_msw); |
12038 | if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) { | 12027 | if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) { |
12039 | } else { | 12028 | } else { |
12040 | if ((pci_device_id == ASC_PCI_DEVICE_ID_REV_A) || | 12029 | if ((pci_device_id == PCI_DEVICE_ID_ASP_1200A) || |
12041 | (pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) { | 12030 | (pci_device_id == PCI_DEVICE_ID_ASP_ABP940)) { |
12042 | asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB; | 12031 | asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB; |
12043 | asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN; | 12032 | asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN; |
12044 | } | 12033 | } |
@@ -14275,8 +14264,8 @@ Default_38C0800_EEPROM_Config __initdata = { | |||
14275 | 0, /* 55 reserved */ | 14264 | 0, /* 55 reserved */ |
14276 | 0, /* 56 cisptr_lsw */ | 14265 | 0, /* 56 cisptr_lsw */ |
14277 | 0, /* 57 cisprt_msw */ | 14266 | 0, /* 57 cisprt_msw */ |
14278 | ADV_PCI_VENDOR_ID, /* 58 subsysvid */ | 14267 | PCI_VENDOR_ID_ASP, /* 58 subsysvid */ |
14279 | ADV_PCI_DEVID_38C0800_REV1, /* 59 subsysid */ | 14268 | PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */ |
14280 | 0, /* 60 reserved */ | 14269 | 0, /* 60 reserved */ |
14281 | 0, /* 61 reserved */ | 14270 | 0, /* 61 reserved */ |
14282 | 0, /* 62 reserved */ | 14271 | 0, /* 62 reserved */ |
@@ -14405,8 +14394,8 @@ Default_38C1600_EEPROM_Config __initdata = { | |||
14405 | 0, /* 55 reserved */ | 14394 | 0, /* 55 reserved */ |
14406 | 0, /* 56 cisptr_lsw */ | 14395 | 0, /* 56 cisptr_lsw */ |
14407 | 0, /* 57 cisprt_msw */ | 14396 | 0, /* 57 cisprt_msw */ |
14408 | ADV_PCI_VENDOR_ID, /* 58 subsysvid */ | 14397 | PCI_VENDOR_ID_ASP, /* 58 subsysvid */ |
14409 | ADV_PCI_DEVID_38C1600_REV1, /* 59 subsysid */ | 14398 | PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */ |
14410 | 0, /* 60 reserved */ | 14399 | 0, /* 60 reserved */ |
14411 | 0, /* 61 reserved */ | 14400 | 0, /* 61 reserved */ |
14412 | 0, /* 62 reserved */ | 14401 | 0, /* 62 reserved */ |
@@ -18225,3 +18214,22 @@ AdvInquiryHandling( | |||
18225 | } | 18214 | } |
18226 | } | 18215 | } |
18227 | MODULE_LICENSE("Dual BSD/GPL"); | 18216 | MODULE_LICENSE("Dual BSD/GPL"); |
18217 | |||
18218 | /* PCI Devices supported by this driver */ | ||
18219 | static struct pci_device_id advansys_pci_tbl[] __devinitdata = { | ||
18220 | { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A, | ||
18221 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
18222 | { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940, | ||
18223 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
18224 | { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U, | ||
18225 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
18226 | { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW, | ||
18227 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
18228 | { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1, | ||
18229 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
18230 | { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1, | ||
18231 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
18232 | { } | ||
18233 | }; | ||
18234 | MODULE_DEVICE_TABLE(pci, advansys_pci_tbl); | ||
18235 | |||
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 998999c0a97..c7eeaced324 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c | |||
@@ -321,7 +321,7 @@ MODULE_LICENSE("Dual BSD/GPL"); | |||
321 | MODULE_VERSION(AIC79XX_DRIVER_VERSION); | 321 | MODULE_VERSION(AIC79XX_DRIVER_VERSION); |
322 | module_param(aic79xx, charp, 0444); | 322 | module_param(aic79xx, charp, 0444); |
323 | MODULE_PARM_DESC(aic79xx, | 323 | MODULE_PARM_DESC(aic79xx, |
324 | "period delimited, options string.\n" | 324 | "period-delimited options string:\n" |
325 | " verbose Enable verbose/diagnostic logging\n" | 325 | " verbose Enable verbose/diagnostic logging\n" |
326 | " allow_memio Allow device registers to be memory mapped\n" | 326 | " allow_memio Allow device registers to be memory mapped\n" |
327 | " debug Bitmask of debug values to enable\n" | 327 | " debug Bitmask of debug values to enable\n" |
@@ -346,7 +346,7 @@ MODULE_PARM_DESC(aic79xx, | |||
346 | " Shorten the selection timeout to 128ms\n" | 346 | " Shorten the selection timeout to 128ms\n" |
347 | "\n" | 347 | "\n" |
348 | " options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n" | 348 | " options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n" |
349 | "\n"); | 349 | ); |
350 | 350 | ||
351 | static void ahd_linux_handle_scsi_status(struct ahd_softc *, | 351 | static void ahd_linux_handle_scsi_status(struct ahd_softc *, |
352 | struct scsi_device *, | 352 | struct scsi_device *, |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index aa4be8a3141..e5bb4d87b30 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
@@ -341,7 +341,7 @@ MODULE_LICENSE("Dual BSD/GPL"); | |||
341 | MODULE_VERSION(AIC7XXX_DRIVER_VERSION); | 341 | MODULE_VERSION(AIC7XXX_DRIVER_VERSION); |
342 | module_param(aic7xxx, charp, 0444); | 342 | module_param(aic7xxx, charp, 0444); |
343 | MODULE_PARM_DESC(aic7xxx, | 343 | MODULE_PARM_DESC(aic7xxx, |
344 | "period delimited, options string.\n" | 344 | "period-delimited options string:\n" |
345 | " verbose Enable verbose/diagnostic logging\n" | 345 | " verbose Enable verbose/diagnostic logging\n" |
346 | " allow_memio Allow device registers to be memory mapped\n" | 346 | " allow_memio Allow device registers to be memory mapped\n" |
347 | " debug Bitmask of debug values to enable\n" | 347 | " debug Bitmask of debug values to enable\n" |
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index 3f85b5e978f..ba3bccafe11 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c | |||
@@ -249,8 +249,6 @@ | |||
249 | #include <linux/stat.h> | 249 | #include <linux/stat.h> |
250 | #include <linux/slab.h> /* for kmalloc() */ | 250 | #include <linux/slab.h> /* for kmalloc() */ |
251 | 251 | ||
252 | #include <linux/config.h> /* for CONFIG_PCI */ | ||
253 | |||
254 | #define AIC7XXX_C_VERSION "5.2.6" | 252 | #define AIC7XXX_C_VERSION "5.2.6" |
255 | 253 | ||
256 | #define ALL_TARGETS -1 | 254 | #define ALL_TARGETS -1 |
diff --git a/drivers/scsi/arcmsr/Makefile b/drivers/scsi/arcmsr/Makefile new file mode 100644 index 00000000000..721aced3916 --- /dev/null +++ b/drivers/scsi/arcmsr/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # File: drivers/arcmsr/Makefile | ||
2 | # Makefile for the ARECA PCI-X PCI-EXPRESS SATA RAID controllers SCSI driver. | ||
3 | |||
4 | arcmsr-objs := arcmsr_attr.o arcmsr_hba.o | ||
5 | |||
6 | obj-$(CONFIG_SCSI_ARCMSR) := arcmsr.o | ||
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h new file mode 100644 index 00000000000..aff96db9ccf --- /dev/null +++ b/drivers/scsi/arcmsr/arcmsr.h | |||
@@ -0,0 +1,472 @@ | |||
1 | /* | ||
2 | ******************************************************************************* | ||
3 | ** O.S : Linux | ||
4 | ** FILE NAME : arcmsr.h | ||
5 | ** BY : Erich Chen | ||
6 | ** Description: SCSI RAID Device Driver for | ||
7 | ** ARECA RAID Host adapter | ||
8 | ******************************************************************************* | ||
9 | ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved. | ||
10 | ** | ||
11 | ** Web site: www.areca.com.tw | ||
12 | ** E-mail: erich@areca.com.tw | ||
13 | ** | ||
14 | ** This program is free software; you can redistribute it and/or modify | ||
15 | ** it under the terms of the GNU General Public License version 2 as | ||
16 | ** published by the Free Software Foundation. | ||
17 | ** This program is distributed in the hope that it will be useful, | ||
18 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | ** GNU General Public License for more details. | ||
21 | ******************************************************************************* | ||
22 | ** Redistribution and use in source and binary forms, with or without | ||
23 | ** modification, are permitted provided that the following conditions | ||
24 | ** are met: | ||
25 | ** 1. Redistributions of source code must retain the above copyright | ||
26 | ** notice, this list of conditions and the following disclaimer. | ||
27 | ** 2. Redistributions in binary form must reproduce the above copyright | ||
28 | ** notice, this list of conditions and the following disclaimer in the | ||
29 | ** documentation and/or other materials provided with the distribution. | ||
30 | ** 3. The name of the author may not be used to endorse or promote products | ||
31 | ** derived from this software without specific prior written permission. | ||
32 | ** | ||
33 | ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
34 | ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
35 | ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
36 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
37 | ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT | ||
38 | ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
39 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY | ||
40 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
41 | **(INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF | ||
42 | ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
43 | ******************************************************************************* | ||
44 | */ | ||
45 | #include <linux/interrupt.h> | ||
46 | |||
47 | struct class_device_attribute; | ||
48 | |||
49 | #define ARCMSR_MAX_OUTSTANDING_CMD 256 | ||
50 | #define ARCMSR_MAX_FREECCB_NUM 288 | ||
51 | #define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.13" | ||
52 | #define ARCMSR_SCSI_INITIATOR_ID 255 | ||
53 | #define ARCMSR_MAX_XFER_SECTORS 512 | ||
54 | #define ARCMSR_MAX_TARGETID 17 | ||
55 | #define ARCMSR_MAX_TARGETLUN 8 | ||
56 | #define ARCMSR_MAX_CMD_PERLUN ARCMSR_MAX_OUTSTANDING_CMD | ||
57 | #define ARCMSR_MAX_QBUFFER 4096 | ||
58 | #define ARCMSR_MAX_SG_ENTRIES 38 | ||
59 | |||
60 | /* | ||
61 | ******************************************************************************* | ||
62 | ** split 64bits dma addressing | ||
63 | ******************************************************************************* | ||
64 | */ | ||
65 | #define dma_addr_hi32(addr) (uint32_t) ((addr>>16)>>16) | ||
66 | #define dma_addr_lo32(addr) (uint32_t) (addr & 0xffffffff) | ||
67 | /* | ||
68 | ******************************************************************************* | ||
69 | ** MESSAGE CONTROL CODE | ||
70 | ******************************************************************************* | ||
71 | */ | ||
72 | struct CMD_MESSAGE | ||
73 | { | ||
74 | uint32_t HeaderLength; | ||
75 | uint8_t Signature[8]; | ||
76 | uint32_t Timeout; | ||
77 | uint32_t ControlCode; | ||
78 | uint32_t ReturnCode; | ||
79 | uint32_t Length; | ||
80 | }; | ||
81 | /* | ||
82 | ******************************************************************************* | ||
83 | ** IOP Message Transfer Data for user space | ||
84 | ******************************************************************************* | ||
85 | */ | ||
86 | struct CMD_MESSAGE_FIELD | ||
87 | { | ||
88 | struct CMD_MESSAGE cmdmessage; | ||
89 | uint8_t messagedatabuffer[1032]; | ||
90 | }; | ||
91 | /* IOP message transfer */ | ||
92 | #define ARCMSR_MESSAGE_FAIL 0x0001 | ||
93 | /* DeviceType */ | ||
94 | #define ARECA_SATA_RAID 0x90000000 | ||
95 | /* FunctionCode */ | ||
96 | #define FUNCTION_READ_RQBUFFER 0x0801 | ||
97 | #define FUNCTION_WRITE_WQBUFFER 0x0802 | ||
98 | #define FUNCTION_CLEAR_RQBUFFER 0x0803 | ||
99 | #define FUNCTION_CLEAR_WQBUFFER 0x0804 | ||
100 | #define FUNCTION_CLEAR_ALLQBUFFER 0x0805 | ||
101 | #define FUNCTION_RETURN_CODE_3F 0x0806 | ||
102 | #define FUNCTION_SAY_HELLO 0x0807 | ||
103 | #define FUNCTION_SAY_GOODBYE 0x0808 | ||
104 | #define FUNCTION_FLUSH_ADAPTER_CACHE 0x0809 | ||
105 | /* ARECA IO CONTROL CODE*/ | ||
106 | #define ARCMSR_MESSAGE_READ_RQBUFFER \ | ||
107 | ARECA_SATA_RAID | FUNCTION_READ_RQBUFFER | ||
108 | #define ARCMSR_MESSAGE_WRITE_WQBUFFER \ | ||
109 | ARECA_SATA_RAID | FUNCTION_WRITE_WQBUFFER | ||
110 | #define ARCMSR_MESSAGE_CLEAR_RQBUFFER \ | ||
111 | ARECA_SATA_RAID | FUNCTION_CLEAR_RQBUFFER | ||
112 | #define ARCMSR_MESSAGE_CLEAR_WQBUFFER \ | ||
113 | ARECA_SATA_RAID | FUNCTION_CLEAR_WQBUFFER | ||
114 | #define ARCMSR_MESSAGE_CLEAR_ALLQBUFFER \ | ||
115 | ARECA_SATA_RAID | FUNCTION_CLEAR_ALLQBUFFER | ||
116 | #define ARCMSR_MESSAGE_RETURN_CODE_3F \ | ||
117 | ARECA_SATA_RAID | FUNCTION_RETURN_CODE_3F | ||
118 | #define ARCMSR_MESSAGE_SAY_HELLO \ | ||
119 | ARECA_SATA_RAID | FUNCTION_SAY_HELLO | ||
120 | #define ARCMSR_MESSAGE_SAY_GOODBYE \ | ||
121 | ARECA_SATA_RAID | FUNCTION_SAY_GOODBYE | ||
122 | #define ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE \ | ||
123 | ARECA_SATA_RAID | FUNCTION_FLUSH_ADAPTER_CACHE | ||
124 | /* ARECA IOCTL ReturnCode */ | ||
125 | #define ARCMSR_MESSAGE_RETURNCODE_OK 0x00000001 | ||
126 | #define ARCMSR_MESSAGE_RETURNCODE_ERROR 0x00000006 | ||
127 | #define ARCMSR_MESSAGE_RETURNCODE_3F 0x0000003F | ||
128 | /* | ||
129 | ************************************************************* | ||
130 | ** structure for holding DMA address data | ||
131 | ************************************************************* | ||
132 | */ | ||
133 | #define IS_SG64_ADDR 0x01000000 /* bit24 */ | ||
134 | struct SG32ENTRY | ||
135 | { | ||
136 | uint32_t length; | ||
137 | uint32_t address; | ||
138 | }; | ||
139 | struct SG64ENTRY | ||
140 | { | ||
141 | uint32_t length; | ||
142 | uint32_t address; | ||
143 | uint32_t addresshigh; | ||
144 | }; | ||
145 | struct SGENTRY_UNION | ||
146 | { | ||
147 | union | ||
148 | { | ||
149 | struct SG32ENTRY sg32entry; | ||
150 | struct SG64ENTRY sg64entry; | ||
151 | }u; | ||
152 | }; | ||
153 | /* | ||
154 | ******************************************************************** | ||
155 | ** Q Buffer of IOP Message Transfer | ||
156 | ******************************************************************** | ||
157 | */ | ||
158 | struct QBUFFER | ||
159 | { | ||
160 | uint32_t data_len; | ||
161 | uint8_t data[124]; | ||
162 | }; | ||
163 | /* | ||
164 | ******************************************************************************* | ||
165 | ** FIRMWARE INFO | ||
166 | ******************************************************************************* | ||
167 | */ | ||
168 | struct FIRMWARE_INFO | ||
169 | { | ||
170 | uint32_t signature; /*0, 00-03*/ | ||
171 | uint32_t request_len; /*1, 04-07*/ | ||
172 | uint32_t numbers_queue; /*2, 08-11*/ | ||
173 | uint32_t sdram_size; /*3, 12-15*/ | ||
174 | uint32_t ide_channels; /*4, 16-19*/ | ||
175 | char vendor[40]; /*5, 20-59*/ | ||
176 | char model[8]; /*15, 60-67*/ | ||
177 | char firmware_ver[16]; /*17, 68-83*/ | ||
178 | char device_map[16]; /*21, 84-99*/ | ||
179 | }; | ||
180 | /* signature of set and get firmware config */ | ||
181 | #define ARCMSR_SIGNATURE_GET_CONFIG 0x87974060 | ||
182 | #define ARCMSR_SIGNATURE_SET_CONFIG 0x87974063 | ||
183 | /* message code of inbound message register */ | ||
184 | #define ARCMSR_INBOUND_MESG0_NOP 0x00000000 | ||
185 | #define ARCMSR_INBOUND_MESG0_GET_CONFIG 0x00000001 | ||
186 | #define ARCMSR_INBOUND_MESG0_SET_CONFIG 0x00000002 | ||
187 | #define ARCMSR_INBOUND_MESG0_ABORT_CMD 0x00000003 | ||
188 | #define ARCMSR_INBOUND_MESG0_STOP_BGRB 0x00000004 | ||
189 | #define ARCMSR_INBOUND_MESG0_FLUSH_CACHE 0x00000005 | ||
190 | #define ARCMSR_INBOUND_MESG0_START_BGRB 0x00000006 | ||
191 | #define ARCMSR_INBOUND_MESG0_CHK331PENDING 0x00000007 | ||
192 | #define ARCMSR_INBOUND_MESG0_SYNC_TIMER 0x00000008 | ||
193 | /* doorbell interrupt generator */ | ||
194 | #define ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK 0x00000001 | ||
195 | #define ARCMSR_INBOUND_DRIVER_DATA_READ_OK 0x00000002 | ||
196 | #define ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK 0x00000001 | ||
197 | #define ARCMSR_OUTBOUND_IOP331_DATA_READ_OK 0x00000002 | ||
198 | /* ccb areca cdb flag */ | ||
199 | #define ARCMSR_CCBPOST_FLAG_SGL_BSIZE 0x80000000 | ||
200 | #define ARCMSR_CCBPOST_FLAG_IAM_BIOS 0x40000000 | ||
201 | #define ARCMSR_CCBREPLY_FLAG_IAM_BIOS 0x40000000 | ||
202 | #define ARCMSR_CCBREPLY_FLAG_ERROR 0x10000000 | ||
203 | /* outbound firmware ok */ | ||
204 | #define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK 0x80000000 | ||
205 | /* | ||
206 | ******************************************************************************* | ||
207 | ** ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504) | ||
208 | ******************************************************************************* | ||
209 | */ | ||
210 | struct ARCMSR_CDB | ||
211 | { | ||
212 | uint8_t Bus; | ||
213 | uint8_t TargetID; | ||
214 | uint8_t LUN; | ||
215 | uint8_t Function; | ||
216 | |||
217 | uint8_t CdbLength; | ||
218 | uint8_t sgcount; | ||
219 | uint8_t Flags; | ||
220 | #define ARCMSR_CDB_FLAG_SGL_BSIZE 0x01 | ||
221 | #define ARCMSR_CDB_FLAG_BIOS 0x02 | ||
222 | #define ARCMSR_CDB_FLAG_WRITE 0x04 | ||
223 | #define ARCMSR_CDB_FLAG_SIMPLEQ 0x00 | ||
224 | #define ARCMSR_CDB_FLAG_HEADQ 0x08 | ||
225 | #define ARCMSR_CDB_FLAG_ORDEREDQ 0x10 | ||
226 | uint8_t Reserved1; | ||
227 | |||
228 | uint32_t Context; | ||
229 | uint32_t DataLength; | ||
230 | |||
231 | uint8_t Cdb[16]; | ||
232 | |||
233 | uint8_t DeviceStatus; | ||
234 | #define ARCMSR_DEV_CHECK_CONDITION 0x02 | ||
235 | #define ARCMSR_DEV_SELECT_TIMEOUT 0xF0 | ||
236 | #define ARCMSR_DEV_ABORTED 0xF1 | ||
237 | #define ARCMSR_DEV_INIT_FAIL 0xF2 | ||
238 | uint8_t SenseData[15]; | ||
239 | |||
240 | union | ||
241 | { | ||
242 | struct SG32ENTRY sg32entry[ARCMSR_MAX_SG_ENTRIES]; | ||
243 | struct SG64ENTRY sg64entry[ARCMSR_MAX_SG_ENTRIES]; | ||
244 | } u; | ||
245 | }; | ||
246 | /* | ||
247 | ******************************************************************************* | ||
248 | ** Messaging Unit (MU) of the Intel R 80331 I/O processor (80331) | ||
249 | ******************************************************************************* | ||
250 | */ | ||
251 | struct MessageUnit | ||
252 | { | ||
253 | uint32_t resrved0[4]; /*0000 000F*/ | ||
254 | uint32_t inbound_msgaddr0; /*0010 0013*/ | ||
255 | uint32_t inbound_msgaddr1; /*0014 0017*/ | ||
256 | uint32_t outbound_msgaddr0; /*0018 001B*/ | ||
257 | uint32_t outbound_msgaddr1; /*001C 001F*/ | ||
258 | uint32_t inbound_doorbell; /*0020 0023*/ | ||
259 | uint32_t inbound_intstatus; /*0024 0027*/ | ||
260 | uint32_t inbound_intmask; /*0028 002B*/ | ||
261 | uint32_t outbound_doorbell; /*002C 002F*/ | ||
262 | uint32_t outbound_intstatus; /*0030 0033*/ | ||
263 | uint32_t outbound_intmask; /*0034 0037*/ | ||
264 | uint32_t reserved1[2]; /*0038 003F*/ | ||
265 | uint32_t inbound_queueport; /*0040 0043*/ | ||
266 | uint32_t outbound_queueport; /*0044 0047*/ | ||
267 | uint32_t reserved2[2]; /*0048 004F*/ | ||
268 | uint32_t reserved3[492]; /*0050 07FF 492*/ | ||
269 | uint32_t reserved4[128]; /*0800 09FF 128*/ | ||
270 | uint32_t message_rwbuffer[256]; /*0a00 0DFF 256*/ | ||
271 | uint32_t message_wbuffer[32]; /*0E00 0E7F 32*/ | ||
272 | uint32_t reserved5[32]; /*0E80 0EFF 32*/ | ||
273 | uint32_t message_rbuffer[32]; /*0F00 0F7F 32*/ | ||
274 | uint32_t reserved6[32]; /*0F80 0FFF 32*/ | ||
275 | }; | ||
276 | /* | ||
277 | ******************************************************************************* | ||
278 | ** Adapter Control Block | ||
279 | ******************************************************************************* | ||
280 | */ | ||
281 | struct AdapterControlBlock | ||
282 | { | ||
283 | struct pci_dev * pdev; | ||
284 | struct Scsi_Host * host; | ||
285 | unsigned long vir2phy_offset; | ||
286 | /* Offset is used in making arc cdb physical to virtual calculations */ | ||
287 | uint32_t outbound_int_enable; | ||
288 | |||
289 | struct MessageUnit __iomem * pmu; | ||
290 | /* message unit ATU inbound base address0 */ | ||
291 | |||
292 | uint32_t acb_flags; | ||
293 | #define ACB_F_SCSISTOPADAPTER 0x0001 | ||
294 | #define ACB_F_MSG_STOP_BGRB 0x0002 | ||
295 | /* stop RAID background rebuild */ | ||
296 | #define ACB_F_MSG_START_BGRB 0x0004 | ||
297 | /* stop RAID background rebuild */ | ||
298 | #define ACB_F_IOPDATA_OVERFLOW 0x0008 | ||
299 | /* iop message data rqbuffer overflow */ | ||
300 | #define ACB_F_MESSAGE_WQBUFFER_CLEARED 0x0010 | ||
301 | /* message clear wqbuffer */ | ||
302 | #define ACB_F_MESSAGE_RQBUFFER_CLEARED 0x0020 | ||
303 | /* message clear rqbuffer */ | ||
304 | #define ACB_F_MESSAGE_WQBUFFER_READED 0x0040 | ||
305 | #define ACB_F_BUS_RESET 0x0080 | ||
306 | #define ACB_F_IOP_INITED 0x0100 | ||
307 | /* iop init */ | ||
308 | |||
309 | struct CommandControlBlock * pccb_pool[ARCMSR_MAX_FREECCB_NUM]; | ||
310 | /* used for memory free */ | ||
311 | struct list_head ccb_free_list; | ||
312 | /* head of free ccb list */ | ||
313 | atomic_t ccboutstandingcount; | ||
314 | |||
315 | void * dma_coherent; | ||
316 | /* dma_coherent used for memory free */ | ||
317 | dma_addr_t dma_coherent_handle; | ||
318 | /* dma_coherent_handle used for memory free */ | ||
319 | |||
320 | uint8_t rqbuffer[ARCMSR_MAX_QBUFFER]; | ||
321 | /* data collection buffer for read from 80331 */ | ||
322 | int32_t rqbuf_firstindex; | ||
323 | /* first of read buffer */ | ||
324 | int32_t rqbuf_lastindex; | ||
325 | /* last of read buffer */ | ||
326 | uint8_t wqbuffer[ARCMSR_MAX_QBUFFER]; | ||
327 | /* data collection buffer for write to 80331 */ | ||
328 | int32_t wqbuf_firstindex; | ||
329 | /* first of write buffer */ | ||
330 | int32_t wqbuf_lastindex; | ||
331 | /* last of write buffer */ | ||
332 | uint8_t devstate[ARCMSR_MAX_TARGETID][ARCMSR_MAX_TARGETLUN]; | ||
333 | /* id0 ..... id15, lun0...lun7 */ | ||
334 | #define ARECA_RAID_GONE 0x55 | ||
335 | #define ARECA_RAID_GOOD 0xaa | ||
336 | uint32_t num_resets; | ||
337 | uint32_t num_aborts; | ||
338 | uint32_t firm_request_len; | ||
339 | uint32_t firm_numbers_queue; | ||
340 | uint32_t firm_sdram_size; | ||
341 | uint32_t firm_hd_channels; | ||
342 | char firm_model[12]; | ||
343 | char firm_version[20]; | ||
344 | };/* HW_DEVICE_EXTENSION */ | ||
345 | /* | ||
346 | ******************************************************************************* | ||
347 | ** Command Control Block | ||
348 | ** this CCB length must be 32 bytes boundary | ||
349 | ******************************************************************************* | ||
350 | */ | ||
351 | struct CommandControlBlock | ||
352 | { | ||
353 | struct ARCMSR_CDB arcmsr_cdb; | ||
354 | /* | ||
355 | ** 0-503 (size of CDB=504): | ||
356 | ** arcmsr messenger scsi command descriptor size 504 bytes | ||
357 | */ | ||
358 | uint32_t cdb_shifted_phyaddr; | ||
359 | /* 504-507 */ | ||
360 | uint32_t reserved1; | ||
361 | /* 508-511 */ | ||
362 | #if BITS_PER_LONG == 64 | ||
363 | /* ======================512+64 bytes======================== */ | ||
364 | struct list_head list; | ||
365 | /* 512-527 16 bytes next/prev ptrs for ccb lists */ | ||
366 | struct scsi_cmnd * pcmd; | ||
367 | /* 528-535 8 bytes pointer of linux scsi command */ | ||
368 | struct AdapterControlBlock * acb; | ||
369 | /* 536-543 8 bytes pointer of acb */ | ||
370 | |||
371 | uint16_t ccb_flags; | ||
372 | /* 544-545 */ | ||
373 | #define CCB_FLAG_READ 0x0000 | ||
374 | #define CCB_FLAG_WRITE 0x0001 | ||
375 | #define CCB_FLAG_ERROR 0x0002 | ||
376 | #define CCB_FLAG_FLUSHCACHE 0x0004 | ||
377 | #define CCB_FLAG_MASTER_ABORTED 0x0008 | ||
378 | uint16_t startdone; | ||
379 | /* 546-547 */ | ||
380 | #define ARCMSR_CCB_DONE 0x0000 | ||
381 | #define ARCMSR_CCB_START 0x55AA | ||
382 | #define ARCMSR_CCB_ABORTED 0xAA55 | ||
383 | #define ARCMSR_CCB_ILLEGAL 0xFFFF | ||
384 | uint32_t reserved2[7]; | ||
385 | /* 548-551 552-555 556-559 560-563 564-567 568-571 572-575 */ | ||
386 | #else | ||
387 | /* ======================512+32 bytes======================== */ | ||
388 | struct list_head list; | ||
389 | /* 512-519 8 bytes next/prev ptrs for ccb lists */ | ||
390 | struct scsi_cmnd * pcmd; | ||
391 | /* 520-523 4 bytes pointer of linux scsi command */ | ||
392 | struct AdapterControlBlock * acb; | ||
393 | /* 524-527 4 bytes pointer of acb */ | ||
394 | |||
395 | uint16_t ccb_flags; | ||
396 | /* 528-529 */ | ||
397 | #define CCB_FLAG_READ 0x0000 | ||
398 | #define CCB_FLAG_WRITE 0x0001 | ||
399 | #define CCB_FLAG_ERROR 0x0002 | ||
400 | #define CCB_FLAG_FLUSHCACHE 0x0004 | ||
401 | #define CCB_FLAG_MASTER_ABORTED 0x0008 | ||
402 | uint16_t startdone; | ||
403 | /* 530-531 */ | ||
404 | #define ARCMSR_CCB_DONE 0x0000 | ||
405 | #define ARCMSR_CCB_START 0x55AA | ||
406 | #define ARCMSR_CCB_ABORTED 0xAA55 | ||
407 | #define ARCMSR_CCB_ILLEGAL 0xFFFF | ||
408 | uint32_t reserved2[3]; | ||
409 | /* 532-535 536-539 540-543 */ | ||
410 | #endif | ||
411 | /* ========================================================== */ | ||
412 | }; | ||
413 | /* | ||
414 | ******************************************************************************* | ||
415 | ** ARECA SCSI sense data | ||
416 | ******************************************************************************* | ||
417 | */ | ||
418 | struct SENSE_DATA | ||
419 | { | ||
420 | uint8_t ErrorCode:7; | ||
421 | #define SCSI_SENSE_CURRENT_ERRORS 0x70 | ||
422 | #define SCSI_SENSE_DEFERRED_ERRORS 0x71 | ||
423 | uint8_t Valid:1; | ||
424 | uint8_t SegmentNumber; | ||
425 | uint8_t SenseKey:4; | ||
426 | uint8_t Reserved:1; | ||
427 | uint8_t IncorrectLength:1; | ||
428 | uint8_t EndOfMedia:1; | ||
429 | uint8_t FileMark:1; | ||
430 | uint8_t Information[4]; | ||
431 | uint8_t AdditionalSenseLength; | ||
432 | uint8_t CommandSpecificInformation[4]; | ||
433 | uint8_t AdditionalSenseCode; | ||
434 | uint8_t AdditionalSenseCodeQualifier; | ||
435 | uint8_t FieldReplaceableUnitCode; | ||
436 | uint8_t SenseKeySpecific[3]; | ||
437 | }; | ||
438 | /* | ||
439 | ******************************************************************************* | ||
440 | ** Outbound Interrupt Status Register - OISR | ||
441 | ******************************************************************************* | ||
442 | */ | ||
443 | #define ARCMSR_MU_OUTBOUND_INTERRUPT_STATUS_REG 0x30 | ||
444 | #define ARCMSR_MU_OUTBOUND_PCI_INT 0x10 | ||
445 | #define ARCMSR_MU_OUTBOUND_POSTQUEUE_INT 0x08 | ||
446 | #define ARCMSR_MU_OUTBOUND_DOORBELL_INT 0x04 | ||
447 | #define ARCMSR_MU_OUTBOUND_MESSAGE1_INT 0x02 | ||
448 | #define ARCMSR_MU_OUTBOUND_MESSAGE0_INT 0x01 | ||
449 | #define ARCMSR_MU_OUTBOUND_HANDLE_INT \ | ||
450 | (ARCMSR_MU_OUTBOUND_MESSAGE0_INT \ | ||
451 | |ARCMSR_MU_OUTBOUND_MESSAGE1_INT \ | ||
452 | |ARCMSR_MU_OUTBOUND_DOORBELL_INT \ | ||
453 | |ARCMSR_MU_OUTBOUND_POSTQUEUE_INT \ | ||
454 | |ARCMSR_MU_OUTBOUND_PCI_INT) | ||
455 | /* | ||
456 | ******************************************************************************* | ||
457 | ** Outbound Interrupt Mask Register - OIMR | ||
458 | ******************************************************************************* | ||
459 | */ | ||
460 | #define ARCMSR_MU_OUTBOUND_INTERRUPT_MASK_REG 0x34 | ||
461 | #define ARCMSR_MU_OUTBOUND_PCI_INTMASKENABLE 0x10 | ||
462 | #define ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE 0x08 | ||
463 | #define ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE 0x04 | ||
464 | #define ARCMSR_MU_OUTBOUND_MESSAGE1_INTMASKENABLE 0x02 | ||
465 | #define ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE 0x01 | ||
466 | #define ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE 0x1F | ||
467 | |||
468 | extern void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb); | ||
469 | extern struct class_device_attribute *arcmsr_host_attrs[]; | ||
470 | extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb); | ||
471 | void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb); | ||
472 | |||
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c new file mode 100644 index 00000000000..12497da5529 --- /dev/null +++ b/drivers/scsi/arcmsr/arcmsr_attr.c | |||
@@ -0,0 +1,381 @@ | |||
1 | /* | ||
2 | ******************************************************************************* | ||
3 | ** O.S : Linux | ||
4 | ** FILE NAME : arcmsr_attr.c | ||
5 | ** BY : Erich Chen | ||
6 | ** Description: attributes exported to sysfs and device host | ||
7 | ******************************************************************************* | ||
8 | ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved | ||
9 | ** | ||
10 | ** Web site: www.areca.com.tw | ||
11 | ** E-mail: erich@areca.com.tw | ||
12 | ** | ||
13 | ** This program is free software; you can redistribute it and/or modify | ||
14 | ** it under the terms of the GNU General Public License version 2 as | ||
15 | ** published by the Free Software Foundation. | ||
16 | ** This program is distributed in the hope that it will be useful, | ||
17 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | ** GNU General Public License for more details. | ||
20 | ******************************************************************************* | ||
21 | ** Redistribution and use in source and binary forms, with or without | ||
22 | ** modification, are permitted provided that the following conditions | ||
23 | ** are met: | ||
24 | ** 1. Redistributions of source code must retain the above copyright | ||
25 | ** notice, this list of conditions and the following disclaimer. | ||
26 | ** 2. Redistributions in binary form must reproduce the above copyright | ||
27 | ** notice, this list of conditions and the following disclaimer in the | ||
28 | ** documentation and/or other materials provided with the distribution. | ||
29 | ** 3. The name of the author may not be used to endorse or promote products | ||
30 | ** derived from this software without specific prior written permission. | ||
31 | ** | ||
32 | ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
33 | ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
34 | ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
35 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
36 | ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING,BUT | ||
37 | ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
38 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY | ||
39 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
40 | ** (INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF | ||
41 | ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
42 | ******************************************************************************* | ||
43 | ** For history of changes, see Documentation/scsi/ChangeLog.arcmsr | ||
44 | ** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt | ||
45 | ******************************************************************************* | ||
46 | */ | ||
47 | #include <linux/module.h> | ||
48 | #include <linux/kernel.h> | ||
49 | #include <linux/init.h> | ||
50 | #include <linux/errno.h> | ||
51 | #include <linux/delay.h> | ||
52 | #include <linux/pci.h> | ||
53 | |||
54 | #include <scsi/scsi_cmnd.h> | ||
55 | #include <scsi/scsi_device.h> | ||
56 | #include <scsi/scsi_host.h> | ||
57 | #include <scsi/scsi_transport.h> | ||
58 | #include "arcmsr.h" | ||
59 | |||
60 | struct class_device_attribute *arcmsr_host_attrs[]; | ||
61 | |||
62 | static ssize_t | ||
63 | arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off, | ||
64 | size_t count) | ||
65 | { | ||
66 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); | ||
67 | struct Scsi_Host *host = class_to_shost(cdev); | ||
68 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | ||
69 | struct MessageUnit __iomem *reg = acb->pmu; | ||
70 | uint8_t *pQbuffer,*ptmpQbuffer; | ||
71 | int32_t allxfer_len = 0; | ||
72 | |||
73 | if (!capable(CAP_SYS_ADMIN)) | ||
74 | return -EACCES; | ||
75 | |||
76 | /* do message unit read. */ | ||
77 | ptmpQbuffer = (uint8_t *)buf; | ||
78 | while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) | ||
79 | && (allxfer_len < 1031)) { | ||
80 | pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; | ||
81 | memcpy(ptmpQbuffer, pQbuffer, 1); | ||
82 | acb->rqbuf_firstindex++; | ||
83 | acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; | ||
84 | ptmpQbuffer++; | ||
85 | allxfer_len++; | ||
86 | } | ||
87 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | ||
88 | struct QBUFFER __iomem * prbuffer = (struct QBUFFER __iomem *) | ||
89 | ®->message_rbuffer; | ||
90 | uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data; | ||
91 | int32_t iop_len; | ||
92 | |||
93 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | ||
94 | iop_len = readl(&prbuffer->data_len); | ||
95 | while (iop_len > 0) { | ||
96 | acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); | ||
97 | acb->rqbuf_lastindex++; | ||
98 | acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; | ||
99 | iop_data++; | ||
100 | iop_len--; | ||
101 | } | ||
102 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, | ||
103 | ®->inbound_doorbell); | ||
104 | } | ||
105 | return (allxfer_len); | ||
106 | } | ||
107 | |||
108 | static ssize_t | ||
109 | arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off, | ||
110 | size_t count) | ||
111 | { | ||
112 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); | ||
113 | struct Scsi_Host *host = class_to_shost(cdev); | ||
114 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | ||
115 | int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; | ||
116 | uint8_t *pQbuffer, *ptmpuserbuffer; | ||
117 | |||
118 | if (!capable(CAP_SYS_ADMIN)) | ||
119 | return -EACCES; | ||
120 | if (count > 1032) | ||
121 | return -EINVAL; | ||
122 | /* do message unit write. */ | ||
123 | ptmpuserbuffer = (uint8_t *)buf; | ||
124 | user_len = (int32_t)count; | ||
125 | wqbuf_lastindex = acb->wqbuf_lastindex; | ||
126 | wqbuf_firstindex = acb->wqbuf_firstindex; | ||
127 | if (wqbuf_lastindex != wqbuf_firstindex) { | ||
128 | arcmsr_post_Qbuffer(acb); | ||
129 | return 0; /*need retry*/ | ||
130 | } else { | ||
131 | my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) | ||
132 | &(ARCMSR_MAX_QBUFFER - 1); | ||
133 | if (my_empty_len >= user_len) { | ||
134 | while (user_len > 0) { | ||
135 | pQbuffer = | ||
136 | &acb->wqbuffer[acb->wqbuf_lastindex]; | ||
137 | memcpy(pQbuffer, ptmpuserbuffer, 1); | ||
138 | acb->wqbuf_lastindex++; | ||
139 | acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; | ||
140 | ptmpuserbuffer++; | ||
141 | user_len--; | ||
142 | } | ||
143 | if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { | ||
144 | acb->acb_flags &= | ||
145 | ~ACB_F_MESSAGE_WQBUFFER_CLEARED; | ||
146 | arcmsr_post_Qbuffer(acb); | ||
147 | } | ||
148 | return count; | ||
149 | } else { | ||
150 | return 0; /*need retry*/ | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | |||
155 | static ssize_t | ||
156 | arcmsr_sysfs_iop_message_clear(struct kobject *kobj, char *buf, loff_t off, | ||
157 | size_t count) | ||
158 | { | ||
159 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); | ||
160 | struct Scsi_Host *host = class_to_shost(cdev); | ||
161 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | ||
162 | struct MessageUnit __iomem *reg = acb->pmu; | ||
163 | uint8_t *pQbuffer; | ||
164 | |||
165 | if (!capable(CAP_SYS_ADMIN)) | ||
166 | return -EACCES; | ||
167 | |||
168 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | ||
169 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | ||
170 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK | ||
171 | , ®->inbound_doorbell); | ||
172 | } | ||
173 | acb->acb_flags |= | ||
174 | (ACB_F_MESSAGE_WQBUFFER_CLEARED | ||
175 | | ACB_F_MESSAGE_RQBUFFER_CLEARED | ||
176 | | ACB_F_MESSAGE_WQBUFFER_READED); | ||
177 | acb->rqbuf_firstindex = 0; | ||
178 | acb->rqbuf_lastindex = 0; | ||
179 | acb->wqbuf_firstindex = 0; | ||
180 | acb->wqbuf_lastindex = 0; | ||
181 | pQbuffer = acb->rqbuffer; | ||
182 | memset(pQbuffer, 0, sizeof (struct QBUFFER)); | ||
183 | pQbuffer = acb->wqbuffer; | ||
184 | memset(pQbuffer, 0, sizeof (struct QBUFFER)); | ||
185 | return 1; | ||
186 | } | ||
187 | |||
188 | static struct bin_attribute arcmsr_sysfs_message_read_attr = { | ||
189 | .attr = { | ||
190 | .name = "mu_read", | ||
191 | .mode = S_IRUSR , | ||
192 | .owner = THIS_MODULE, | ||
193 | }, | ||
194 | .size = 1032, | ||
195 | .read = arcmsr_sysfs_iop_message_read, | ||
196 | }; | ||
197 | |||
198 | static struct bin_attribute arcmsr_sysfs_message_write_attr = { | ||
199 | .attr = { | ||
200 | .name = "mu_write", | ||
201 | .mode = S_IWUSR, | ||
202 | .owner = THIS_MODULE, | ||
203 | }, | ||
204 | .size = 1032, | ||
205 | .write = arcmsr_sysfs_iop_message_write, | ||
206 | }; | ||
207 | |||
208 | static struct bin_attribute arcmsr_sysfs_message_clear_attr = { | ||
209 | .attr = { | ||
210 | .name = "mu_clear", | ||
211 | .mode = S_IWUSR, | ||
212 | .owner = THIS_MODULE, | ||
213 | }, | ||
214 | .size = 1, | ||
215 | .write = arcmsr_sysfs_iop_message_clear, | ||
216 | }; | ||
217 | |||
218 | int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb) | ||
219 | { | ||
220 | struct Scsi_Host *host = acb->host; | ||
221 | int error; | ||
222 | |||
223 | error = sysfs_create_bin_file(&host->shost_classdev.kobj, | ||
224 | &arcmsr_sysfs_message_read_attr); | ||
225 | if (error) { | ||
226 | printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n"); | ||
227 | goto error_bin_file_message_read; | ||
228 | } | ||
229 | error = sysfs_create_bin_file(&host->shost_classdev.kobj, | ||
230 | &arcmsr_sysfs_message_write_attr); | ||
231 | if (error) { | ||
232 | printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n"); | ||
233 | goto error_bin_file_message_write; | ||
234 | } | ||
235 | error = sysfs_create_bin_file(&host->shost_classdev.kobj, | ||
236 | &arcmsr_sysfs_message_clear_attr); | ||
237 | if (error) { | ||
238 | printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n"); | ||
239 | goto error_bin_file_message_clear; | ||
240 | } | ||
241 | return 0; | ||
242 | error_bin_file_message_clear: | ||
243 | sysfs_remove_bin_file(&host->shost_classdev.kobj, | ||
244 | &arcmsr_sysfs_message_write_attr); | ||
245 | error_bin_file_message_write: | ||
246 | sysfs_remove_bin_file(&host->shost_classdev.kobj, | ||
247 | &arcmsr_sysfs_message_read_attr); | ||
248 | error_bin_file_message_read: | ||
249 | return error; | ||
250 | } | ||
251 | |||
252 | void | ||
253 | arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) { | ||
254 | struct Scsi_Host *host = acb->host; | ||
255 | |||
256 | sysfs_remove_bin_file(&host->shost_classdev.kobj, | ||
257 | &arcmsr_sysfs_message_clear_attr); | ||
258 | sysfs_remove_bin_file(&host->shost_classdev.kobj, | ||
259 | &arcmsr_sysfs_message_write_attr); | ||
260 | sysfs_remove_bin_file(&host->shost_classdev.kobj, | ||
261 | &arcmsr_sysfs_message_read_attr); | ||
262 | } | ||
263 | |||
264 | |||
265 | static ssize_t | ||
266 | arcmsr_attr_host_driver_version(struct class_device *cdev, char *buf) { | ||
267 | return snprintf(buf, PAGE_SIZE, | ||
268 | "%s\n", | ||
269 | ARCMSR_DRIVER_VERSION); | ||
270 | } | ||
271 | |||
272 | static ssize_t | ||
273 | arcmsr_attr_host_driver_posted_cmd(struct class_device *cdev, char *buf) { | ||
274 | struct Scsi_Host *host = class_to_shost(cdev); | ||
275 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | ||
276 | return snprintf(buf, PAGE_SIZE, | ||
277 | "%4d\n", | ||
278 | atomic_read(&acb->ccboutstandingcount)); | ||
279 | } | ||
280 | |||
281 | static ssize_t | ||
282 | arcmsr_attr_host_driver_reset(struct class_device *cdev, char *buf) { | ||
283 | struct Scsi_Host *host = class_to_shost(cdev); | ||
284 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | ||
285 | return snprintf(buf, PAGE_SIZE, | ||
286 | "%4d\n", | ||
287 | acb->num_resets); | ||
288 | } | ||
289 | |||
290 | static ssize_t | ||
291 | arcmsr_attr_host_driver_abort(struct class_device *cdev, char *buf) { | ||
292 | struct Scsi_Host *host = class_to_shost(cdev); | ||
293 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | ||
294 | return snprintf(buf, PAGE_SIZE, | ||
295 | "%4d\n", | ||
296 | acb->num_aborts); | ||
297 | } | ||
298 | |||
299 | static ssize_t | ||
300 | arcmsr_attr_host_fw_model(struct class_device *cdev, char *buf) { | ||
301 | struct Scsi_Host *host = class_to_shost(cdev); | ||
302 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | ||
303 | return snprintf(buf, PAGE_SIZE, | ||
304 | "%s\n", | ||
305 | acb->firm_model); | ||
306 | } | ||
307 | |||
308 | static ssize_t | ||
309 | arcmsr_attr_host_fw_version(struct class_device *cdev, char *buf) { | ||
310 | struct Scsi_Host *host = class_to_shost(cdev); | ||
311 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | ||
312 | |||
313 | return snprintf(buf, PAGE_SIZE, | ||
314 | "%s\n", | ||
315 | acb->firm_version); | ||
316 | } | ||
317 | |||
318 | static ssize_t | ||
319 | arcmsr_attr_host_fw_request_len(struct class_device *cdev, char *buf) { | ||
320 | struct Scsi_Host *host = class_to_shost(cdev); | ||
321 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | ||
322 | |||
323 | return snprintf(buf, PAGE_SIZE, | ||
324 | "%4d\n", | ||
325 | acb->firm_request_len); | ||
326 | } | ||
327 | |||
328 | static ssize_t | ||
329 | arcmsr_attr_host_fw_numbers_queue(struct class_device *cdev, char *buf) { | ||
330 | struct Scsi_Host *host = class_to_shost(cdev); | ||
331 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | ||
332 | |||
333 | return snprintf(buf, PAGE_SIZE, | ||
334 | "%4d\n", | ||
335 | acb->firm_numbers_queue); | ||
336 | } | ||
337 | |||
338 | static ssize_t | ||
339 | arcmsr_attr_host_fw_sdram_size(struct class_device *cdev, char *buf) { | ||
340 | struct Scsi_Host *host = class_to_shost(cdev); | ||
341 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | ||
342 | |||
343 | return snprintf(buf, PAGE_SIZE, | ||
344 | "%4d\n", | ||
345 | acb->firm_sdram_size); | ||
346 | } | ||
347 | |||
348 | static ssize_t | ||
349 | arcmsr_attr_host_fw_hd_channels(struct class_device *cdev, char *buf) { | ||
350 | struct Scsi_Host *host = class_to_shost(cdev); | ||
351 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; | ||
352 | |||
353 | return snprintf(buf, PAGE_SIZE, | ||
354 | "%4d\n", | ||
355 | acb->firm_hd_channels); | ||
356 | } | ||
357 | |||
358 | static CLASS_DEVICE_ATTR(host_driver_version, S_IRUGO, arcmsr_attr_host_driver_version, NULL); | ||
359 | static CLASS_DEVICE_ATTR(host_driver_posted_cmd, S_IRUGO, arcmsr_attr_host_driver_posted_cmd, NULL); | ||
360 | static CLASS_DEVICE_ATTR(host_driver_reset, S_IRUGO, arcmsr_attr_host_driver_reset, NULL); | ||
361 | static CLASS_DEVICE_ATTR(host_driver_abort, S_IRUGO, arcmsr_attr_host_driver_abort, NULL); | ||
362 | static CLASS_DEVICE_ATTR(host_fw_model, S_IRUGO, arcmsr_attr_host_fw_model, NULL); | ||
363 | static CLASS_DEVICE_ATTR(host_fw_version, S_IRUGO, arcmsr_attr_host_fw_version, NULL); | ||
364 | static CLASS_DEVICE_ATTR(host_fw_request_len, S_IRUGO, arcmsr_attr_host_fw_request_len, NULL); | ||
365 | static CLASS_DEVICE_ATTR(host_fw_numbers_queue, S_IRUGO, arcmsr_attr_host_fw_numbers_queue, NULL); | ||
366 | static CLASS_DEVICE_ATTR(host_fw_sdram_size, S_IRUGO, arcmsr_attr_host_fw_sdram_size, NULL); | ||
367 | static CLASS_DEVICE_ATTR(host_fw_hd_channels, S_IRUGO, arcmsr_attr_host_fw_hd_channels, NULL); | ||
368 | |||
369 | struct class_device_attribute *arcmsr_host_attrs[] = { | ||
370 | &class_device_attr_host_driver_version, | ||
371 | &class_device_attr_host_driver_posted_cmd, | ||
372 | &class_device_attr_host_driver_reset, | ||
373 | &class_device_attr_host_driver_abort, | ||
374 | &class_device_attr_host_fw_model, | ||
375 | &class_device_attr_host_fw_version, | ||
376 | &class_device_attr_host_fw_request_len, | ||
377 | &class_device_attr_host_fw_numbers_queue, | ||
378 | &class_device_attr_host_fw_sdram_size, | ||
379 | &class_device_attr_host_fw_hd_channels, | ||
380 | NULL, | ||
381 | }; | ||
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c new file mode 100644 index 00000000000..475f978ff8f --- /dev/null +++ b/drivers/scsi/arcmsr/arcmsr_hba.c | |||
@@ -0,0 +1,1496 @@ | |||
1 | /* | ||
2 | ******************************************************************************* | ||
3 | ** O.S : Linux | ||
4 | ** FILE NAME : arcmsr_hba.c | ||
5 | ** BY : Erich Chen | ||
6 | ** Description: SCSI RAID Device Driver for | ||
7 | ** ARECA RAID Host adapter | ||
8 | ******************************************************************************* | ||
9 | ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved | ||
10 | ** | ||
11 | ** Web site: www.areca.com.tw | ||
12 | ** E-mail: erich@areca.com.tw | ||
13 | ** | ||
14 | ** This program is free software; you can redistribute it and/or modify | ||
15 | ** it under the terms of the GNU General Public License version 2 as | ||
16 | ** published by the Free Software Foundation. | ||
17 | ** This program is distributed in the hope that it will be useful, | ||
18 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | ** GNU General Public License for more details. | ||
21 | ******************************************************************************* | ||
22 | ** Redistribution and use in source and binary forms, with or without | ||
23 | ** modification, are permitted provided that the following conditions | ||
24 | ** are met: | ||
25 | ** 1. Redistributions of source code must retain the above copyright | ||
26 | ** notice, this list of conditions and the following disclaimer. | ||
27 | ** 2. Redistributions in binary form must reproduce the above copyright | ||
28 | ** notice, this list of conditions and the following disclaimer in the | ||
29 | ** documentation and/or other materials provided with the distribution. | ||
30 | ** 3. The name of the author may not be used to endorse or promote products | ||
31 | ** derived from this software without specific prior written permission. | ||
32 | ** | ||
33 | ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
34 | ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
35 | ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
36 | ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
37 | ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING,BUT | ||
38 | ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
39 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY | ||
40 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
41 | ** (INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF | ||
42 | ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
43 | ******************************************************************************* | ||
44 | ** For history of changes, see Documentation/scsi/ChangeLog.arcmsr | ||
45 | ** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt | ||
46 | ******************************************************************************* | ||
47 | */ | ||
48 | #include <linux/module.h> | ||
49 | #include <linux/reboot.h> | ||
50 | #include <linux/spinlock.h> | ||
51 | #include <linux/pci_ids.h> | ||
52 | #include <linux/interrupt.h> | ||
53 | #include <linux/moduleparam.h> | ||
54 | #include <linux/errno.h> | ||
55 | #include <linux/types.h> | ||
56 | #include <linux/delay.h> | ||
57 | #include <linux/dma-mapping.h> | ||
58 | #include <linux/timer.h> | ||
59 | #include <linux/pci.h> | ||
60 | #include <asm/dma.h> | ||
61 | #include <asm/io.h> | ||
62 | #include <asm/system.h> | ||
63 | #include <asm/uaccess.h> | ||
64 | #include <scsi/scsi_host.h> | ||
65 | #include <scsi/scsi.h> | ||
66 | #include <scsi/scsi_cmnd.h> | ||
67 | #include <scsi/scsi_tcq.h> | ||
68 | #include <scsi/scsi_device.h> | ||
69 | #include <scsi/scsi_transport.h> | ||
70 | #include <scsi/scsicam.h> | ||
71 | #include "arcmsr.h" | ||
72 | |||
73 | MODULE_AUTHOR("Erich Chen <erich@areca.com.tw>"); | ||
74 | MODULE_DESCRIPTION("ARECA (ARC11xx/12xx) SATA RAID HOST Adapter"); | ||
75 | MODULE_LICENSE("Dual BSD/GPL"); | ||
76 | MODULE_VERSION(ARCMSR_DRIVER_VERSION); | ||
77 | |||
78 | static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_cmnd *cmd); | ||
79 | static int arcmsr_abort(struct scsi_cmnd *); | ||
80 | static int arcmsr_bus_reset(struct scsi_cmnd *); | ||
81 | static int arcmsr_bios_param(struct scsi_device *sdev, | ||
82 | struct block_device *bdev, sector_t capacity, int *info); | ||
83 | static int arcmsr_queue_command(struct scsi_cmnd * cmd, | ||
84 | void (*done) (struct scsi_cmnd *)); | ||
85 | static int arcmsr_probe(struct pci_dev *pdev, | ||
86 | const struct pci_device_id *id); | ||
87 | static void arcmsr_remove(struct pci_dev *pdev); | ||
88 | static void arcmsr_shutdown(struct pci_dev *pdev); | ||
89 | static void arcmsr_iop_init(struct AdapterControlBlock *acb); | ||
90 | static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb); | ||
91 | static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); | ||
92 | static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); | ||
93 | static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb); | ||
94 | static const char *arcmsr_info(struct Scsi_Host *); | ||
95 | static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); | ||
96 | |||
97 | static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth) | ||
98 | { | ||
99 | if (queue_depth > ARCMSR_MAX_CMD_PERLUN) | ||
100 | queue_depth = ARCMSR_MAX_CMD_PERLUN; | ||
101 | scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); | ||
102 | return queue_depth; | ||
103 | } | ||
104 | |||
105 | static struct scsi_host_template arcmsr_scsi_host_template = { | ||
106 | .module = THIS_MODULE, | ||
107 | .name = "ARCMSR ARECA SATA RAID HOST Adapter" ARCMSR_DRIVER_VERSION, | ||
108 | .info = arcmsr_info, | ||
109 | .queuecommand = arcmsr_queue_command, | ||
110 | .eh_abort_handler = arcmsr_abort, | ||
111 | .eh_bus_reset_handler = arcmsr_bus_reset, | ||
112 | .bios_param = arcmsr_bios_param, | ||
113 | .change_queue_depth = arcmsr_adjust_disk_queue_depth, | ||
114 | .can_queue = ARCMSR_MAX_OUTSTANDING_CMD, | ||
115 | .this_id = ARCMSR_SCSI_INITIATOR_ID, | ||
116 | .sg_tablesize = ARCMSR_MAX_SG_ENTRIES, | ||
117 | .max_sectors = ARCMSR_MAX_XFER_SECTORS, | ||
118 | .cmd_per_lun = ARCMSR_MAX_CMD_PERLUN, | ||
119 | .use_clustering = ENABLE_CLUSTERING, | ||
120 | .shost_attrs = arcmsr_host_attrs, | ||
121 | }; | ||
122 | |||
123 | static struct pci_device_id arcmsr_device_id_table[] = { | ||
124 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)}, | ||
125 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1120)}, | ||
126 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1130)}, | ||
127 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1160)}, | ||
128 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1170)}, | ||
129 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1210)}, | ||
130 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1220)}, | ||
131 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1230)}, | ||
132 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1260)}, | ||
133 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1270)}, | ||
134 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1280)}, | ||
135 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1380)}, | ||
136 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1381)}, | ||
137 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1680)}, | ||
138 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1681)}, | ||
139 | {0, 0}, /* Terminating entry */ | ||
140 | }; | ||
141 | MODULE_DEVICE_TABLE(pci, arcmsr_device_id_table); | ||
142 | static struct pci_driver arcmsr_pci_driver = { | ||
143 | .name = "arcmsr", | ||
144 | .id_table = arcmsr_device_id_table, | ||
145 | .probe = arcmsr_probe, | ||
146 | .remove = arcmsr_remove, | ||
147 | .shutdown = arcmsr_shutdown | ||
148 | }; | ||
149 | |||
150 | static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id, | ||
151 | struct pt_regs *regs) | ||
152 | { | ||
153 | irqreturn_t handle_state; | ||
154 | struct AdapterControlBlock *acb; | ||
155 | unsigned long flags; | ||
156 | |||
157 | acb = (struct AdapterControlBlock *)dev_id; | ||
158 | |||
159 | spin_lock_irqsave(acb->host->host_lock, flags); | ||
160 | handle_state = arcmsr_interrupt(acb); | ||
161 | spin_unlock_irqrestore(acb->host->host_lock, flags); | ||
162 | return handle_state; | ||
163 | } | ||
164 | |||
165 | static int arcmsr_bios_param(struct scsi_device *sdev, | ||
166 | struct block_device *bdev, sector_t capacity, int *geom) | ||
167 | { | ||
168 | int ret, heads, sectors, cylinders, total_capacity; | ||
169 | unsigned char *buffer;/* return copy of block device's partition table */ | ||
170 | |||
171 | buffer = scsi_bios_ptable(bdev); | ||
172 | if (buffer) { | ||
173 | ret = scsi_partsize(buffer, capacity, &geom[2], &geom[0], &geom[1]); | ||
174 | kfree(buffer); | ||
175 | if (ret != -1) | ||
176 | return ret; | ||
177 | } | ||
178 | total_capacity = capacity; | ||
179 | heads = 64; | ||
180 | sectors = 32; | ||
181 | cylinders = total_capacity / (heads * sectors); | ||
182 | if (cylinders > 1024) { | ||
183 | heads = 255; | ||
184 | sectors = 63; | ||
185 | cylinders = total_capacity / (heads * sectors); | ||
186 | } | ||
187 | geom[0] = heads; | ||
188 | geom[1] = sectors; | ||
189 | geom[2] = cylinders; | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) | ||
194 | { | ||
195 | struct pci_dev *pdev = acb->pdev; | ||
196 | struct MessageUnit __iomem *reg = acb->pmu; | ||
197 | u32 ccb_phyaddr_hi32; | ||
198 | void *dma_coherent; | ||
199 | dma_addr_t dma_coherent_handle, dma_addr; | ||
200 | struct CommandControlBlock *ccb_tmp; | ||
201 | int i, j; | ||
202 | |||
203 | dma_coherent = dma_alloc_coherent(&pdev->dev, | ||
204 | ARCMSR_MAX_FREECCB_NUM * | ||
205 | sizeof (struct CommandControlBlock) + 0x20, | ||
206 | &dma_coherent_handle, GFP_KERNEL); | ||
207 | if (!dma_coherent) | ||
208 | return -ENOMEM; | ||
209 | |||
210 | acb->dma_coherent = dma_coherent; | ||
211 | acb->dma_coherent_handle = dma_coherent_handle; | ||
212 | |||
213 | if (((unsigned long)dma_coherent & 0x1F)) { | ||
214 | dma_coherent = dma_coherent + | ||
215 | (0x20 - ((unsigned long)dma_coherent & 0x1F)); | ||
216 | dma_coherent_handle = dma_coherent_handle + | ||
217 | (0x20 - ((unsigned long)dma_coherent_handle & 0x1F)); | ||
218 | } | ||
219 | |||
220 | dma_addr = dma_coherent_handle; | ||
221 | ccb_tmp = (struct CommandControlBlock *)dma_coherent; | ||
222 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { | ||
223 | ccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5; | ||
224 | ccb_tmp->acb = acb; | ||
225 | acb->pccb_pool[i] = ccb_tmp; | ||
226 | list_add_tail(&ccb_tmp->list, &acb->ccb_free_list); | ||
227 | dma_addr = dma_addr + sizeof (struct CommandControlBlock); | ||
228 | ccb_tmp++; | ||
229 | } | ||
230 | |||
231 | acb->vir2phy_offset = (unsigned long)ccb_tmp - | ||
232 | (unsigned long)dma_addr; | ||
233 | for (i = 0; i < ARCMSR_MAX_TARGETID; i++) | ||
234 | for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) | ||
235 | acb->devstate[i][j] = ARECA_RAID_GOOD; | ||
236 | |||
237 | /* | ||
238 | ** here we need to tell iop 331 our ccb_tmp.HighPart | ||
239 | ** if ccb_tmp.HighPart is not zero | ||
240 | */ | ||
241 | ccb_phyaddr_hi32 = (uint32_t) ((dma_coherent_handle >> 16) >> 16); | ||
242 | if (ccb_phyaddr_hi32 != 0) { | ||
243 | writel(ARCMSR_SIGNATURE_SET_CONFIG, ®->message_rwbuffer[0]); | ||
244 | writel(ccb_phyaddr_hi32, ®->message_rwbuffer[1]); | ||
245 | writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, ®->inbound_msgaddr0); | ||
246 | if (arcmsr_wait_msgint_ready(acb)) | ||
247 | printk(KERN_NOTICE "arcmsr%d: " | ||
248 | "'set ccb high part physical address' timeout\n", | ||
249 | acb->host->host_no); | ||
250 | } | ||
251 | |||
252 | writel(readl(®->outbound_intmask) | | ||
253 | ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, | ||
254 | ®->outbound_intmask); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int arcmsr_probe(struct pci_dev *pdev, | ||
259 | const struct pci_device_id *id) | ||
260 | { | ||
261 | struct Scsi_Host *host; | ||
262 | struct AdapterControlBlock *acb; | ||
263 | uint8_t bus, dev_fun; | ||
264 | int error; | ||
265 | |||
266 | error = pci_enable_device(pdev); | ||
267 | if (error) | ||
268 | goto out; | ||
269 | pci_set_master(pdev); | ||
270 | |||
271 | host = scsi_host_alloc(&arcmsr_scsi_host_template, | ||
272 | sizeof(struct AdapterControlBlock)); | ||
273 | if (!host) { | ||
274 | error = -ENOMEM; | ||
275 | goto out_disable_device; | ||
276 | } | ||
277 | acb = (struct AdapterControlBlock *)host->hostdata; | ||
278 | memset(acb, 0, sizeof (struct AdapterControlBlock)); | ||
279 | |||
280 | error = pci_set_dma_mask(pdev, DMA_64BIT_MASK); | ||
281 | if (error) { | ||
282 | error = pci_set_dma_mask(pdev, DMA_32BIT_MASK); | ||
283 | if (error) { | ||
284 | printk(KERN_WARNING | ||
285 | "scsi%d: No suitable DMA mask available\n", | ||
286 | host->host_no); | ||
287 | goto out_host_put; | ||
288 | } | ||
289 | } | ||
290 | bus = pdev->bus->number; | ||
291 | dev_fun = pdev->devfn; | ||
292 | acb->host = host; | ||
293 | acb->pdev = pdev; | ||
294 | host->max_sectors = ARCMSR_MAX_XFER_SECTORS; | ||
295 | host->max_lun = ARCMSR_MAX_TARGETLUN; | ||
296 | host->max_id = ARCMSR_MAX_TARGETID;/*16:8*/ | ||
297 | host->max_cmd_len = 16; /*this is issue of 64bit LBA, over 2T byte*/ | ||
298 | host->sg_tablesize = ARCMSR_MAX_SG_ENTRIES; | ||
299 | host->can_queue = ARCMSR_MAX_FREECCB_NUM; /* max simultaneous cmds */ | ||
300 | host->cmd_per_lun = ARCMSR_MAX_CMD_PERLUN; | ||
301 | host->this_id = ARCMSR_SCSI_INITIATOR_ID; | ||
302 | host->unique_id = (bus << 8) | dev_fun; | ||
303 | host->irq = pdev->irq; | ||
304 | error = pci_request_regions(pdev, "arcmsr"); | ||
305 | if (error) | ||
306 | goto out_host_put; | ||
307 | |||
308 | acb->pmu = ioremap(pci_resource_start(pdev, 0), | ||
309 | pci_resource_len(pdev, 0)); | ||
310 | if (!acb->pmu) { | ||
311 | printk(KERN_NOTICE "arcmsr%d: memory" | ||
312 | " mapping region fail \n", acb->host->host_no); | ||
313 | goto out_release_regions; | ||
314 | } | ||
315 | acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | | ||
316 | ACB_F_MESSAGE_RQBUFFER_CLEARED | | ||
317 | ACB_F_MESSAGE_WQBUFFER_READED); | ||
318 | acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; | ||
319 | INIT_LIST_HEAD(&acb->ccb_free_list); | ||
320 | |||
321 | error = arcmsr_alloc_ccb_pool(acb); | ||
322 | if (error) | ||
323 | goto out_iounmap; | ||
324 | |||
325 | error = request_irq(pdev->irq, arcmsr_do_interrupt, | ||
326 | SA_INTERRUPT | SA_SHIRQ, "arcmsr", acb); | ||
327 | if (error) | ||
328 | goto out_free_ccb_pool; | ||
329 | |||
330 | arcmsr_iop_init(acb); | ||
331 | pci_set_drvdata(pdev, host); | ||
332 | |||
333 | error = scsi_add_host(host, &pdev->dev); | ||
334 | if (error) | ||
335 | goto out_free_irq; | ||
336 | |||
337 | error = arcmsr_alloc_sysfs_attr(acb); | ||
338 | if (error) | ||
339 | goto out_free_sysfs; | ||
340 | |||
341 | scsi_scan_host(host); | ||
342 | return 0; | ||
343 | out_free_sysfs: | ||
344 | out_free_irq: | ||
345 | free_irq(pdev->irq, acb); | ||
346 | out_free_ccb_pool: | ||
347 | arcmsr_free_ccb_pool(acb); | ||
348 | out_iounmap: | ||
349 | iounmap(acb->pmu); | ||
350 | out_release_regions: | ||
351 | pci_release_regions(pdev); | ||
352 | out_host_put: | ||
353 | scsi_host_put(host); | ||
354 | out_disable_device: | ||
355 | pci_disable_device(pdev); | ||
356 | out: | ||
357 | return error; | ||
358 | } | ||
359 | |||
360 | static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) | ||
361 | { | ||
362 | struct MessageUnit __iomem *reg = acb->pmu; | ||
363 | |||
364 | writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); | ||
365 | if (arcmsr_wait_msgint_ready(acb)) | ||
366 | printk(KERN_NOTICE | ||
367 | "arcmsr%d: wait 'abort all outstanding command' timeout \n" | ||
368 | , acb->host->host_no); | ||
369 | } | ||
370 | |||
371 | static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) | ||
372 | { | ||
373 | struct AdapterControlBlock *acb = ccb->acb; | ||
374 | struct scsi_cmnd *pcmd = ccb->pcmd; | ||
375 | |||
376 | if (pcmd->use_sg != 0) { | ||
377 | struct scatterlist *sl; | ||
378 | |||
379 | sl = (struct scatterlist *)pcmd->request_buffer; | ||
380 | pci_unmap_sg(acb->pdev, sl, pcmd->use_sg, pcmd->sc_data_direction); | ||
381 | } | ||
382 | else if (pcmd->request_bufflen != 0) | ||
383 | pci_unmap_single(acb->pdev, | ||
384 | pcmd->SCp.dma_handle, | ||
385 | pcmd->request_bufflen, pcmd->sc_data_direction); | ||
386 | } | ||
387 | |||
388 | static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag) | ||
389 | { | ||
390 | struct AdapterControlBlock *acb = ccb->acb; | ||
391 | struct scsi_cmnd *pcmd = ccb->pcmd; | ||
392 | |||
393 | arcmsr_pci_unmap_dma(ccb); | ||
394 | if (stand_flag == 1) | ||
395 | atomic_dec(&acb->ccboutstandingcount); | ||
396 | ccb->startdone = ARCMSR_CCB_DONE; | ||
397 | ccb->ccb_flags = 0; | ||
398 | list_add_tail(&ccb->list, &acb->ccb_free_list); | ||
399 | pcmd->scsi_done(pcmd); | ||
400 | } | ||
401 | |||
402 | static void arcmsr_remove(struct pci_dev *pdev) | ||
403 | { | ||
404 | struct Scsi_Host *host = pci_get_drvdata(pdev); | ||
405 | struct AdapterControlBlock *acb = | ||
406 | (struct AdapterControlBlock *) host->hostdata; | ||
407 | struct MessageUnit __iomem *reg = acb->pmu; | ||
408 | int poll_count = 0; | ||
409 | |||
410 | arcmsr_free_sysfs_attr(acb); | ||
411 | scsi_remove_host(host); | ||
412 | arcmsr_stop_adapter_bgrb(acb); | ||
413 | arcmsr_flush_adapter_cache(acb); | ||
414 | writel(readl(®->outbound_intmask) | | ||
415 | ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, | ||
416 | ®->outbound_intmask); | ||
417 | acb->acb_flags |= ACB_F_SCSISTOPADAPTER; | ||
418 | acb->acb_flags &= ~ACB_F_IOP_INITED; | ||
419 | |||
420 | for (poll_count = 0; poll_count < 256; poll_count++) { | ||
421 | if (!atomic_read(&acb->ccboutstandingcount)) | ||
422 | break; | ||
423 | arcmsr_interrupt(acb); | ||
424 | msleep(25); | ||
425 | } | ||
426 | |||
427 | if (atomic_read(&acb->ccboutstandingcount)) { | ||
428 | int i; | ||
429 | |||
430 | arcmsr_abort_allcmd(acb); | ||
431 | for (i = 0; i < ARCMSR_MAX_OUTSTANDING_CMD; i++) | ||
432 | readl(®->outbound_queueport); | ||
433 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { | ||
434 | struct CommandControlBlock *ccb = acb->pccb_pool[i]; | ||
435 | if (ccb->startdone == ARCMSR_CCB_START) { | ||
436 | ccb->startdone = ARCMSR_CCB_ABORTED; | ||
437 | ccb->pcmd->result = DID_ABORT << 16; | ||
438 | arcmsr_ccb_complete(ccb, 1); | ||
439 | } | ||
440 | } | ||
441 | } | ||
442 | |||
443 | free_irq(pdev->irq, acb); | ||
444 | iounmap(acb->pmu); | ||
445 | arcmsr_free_ccb_pool(acb); | ||
446 | pci_release_regions(pdev); | ||
447 | |||
448 | scsi_host_put(host); | ||
449 | |||
450 | pci_disable_device(pdev); | ||
451 | pci_set_drvdata(pdev, NULL); | ||
452 | } | ||
453 | |||
454 | static void arcmsr_shutdown(struct pci_dev *pdev) | ||
455 | { | ||
456 | struct Scsi_Host *host = pci_get_drvdata(pdev); | ||
457 | struct AdapterControlBlock *acb = | ||
458 | (struct AdapterControlBlock *)host->hostdata; | ||
459 | |||
460 | arcmsr_stop_adapter_bgrb(acb); | ||
461 | arcmsr_flush_adapter_cache(acb); | ||
462 | } | ||
463 | |||
464 | static int arcmsr_module_init(void) | ||
465 | { | ||
466 | int error = 0; | ||
467 | |||
468 | error = pci_register_driver(&arcmsr_pci_driver); | ||
469 | return error; | ||
470 | } | ||
471 | |||
472 | static void arcmsr_module_exit(void) | ||
473 | { | ||
474 | pci_unregister_driver(&arcmsr_pci_driver); | ||
475 | } | ||
476 | module_init(arcmsr_module_init); | ||
477 | module_exit(arcmsr_module_exit); | ||
478 | |||
479 | static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) | ||
480 | { | ||
481 | struct MessageUnit __iomem *reg = acb->pmu; | ||
482 | u32 orig_mask = readl(®->outbound_intmask); | ||
483 | |||
484 | writel(orig_mask | ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, | ||
485 | ®->outbound_intmask); | ||
486 | return orig_mask; | ||
487 | } | ||
488 | |||
489 | static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, | ||
490 | u32 orig_mask) | ||
491 | { | ||
492 | struct MessageUnit __iomem *reg = acb->pmu; | ||
493 | u32 mask; | ||
494 | |||
495 | mask = orig_mask & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | | ||
496 | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); | ||
497 | writel(mask, ®->outbound_intmask); | ||
498 | } | ||
499 | |||
500 | static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) | ||
501 | { | ||
502 | struct MessageUnit __iomem *reg=acb->pmu; | ||
503 | |||
504 | writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); | ||
505 | if (arcmsr_wait_msgint_ready(acb)) | ||
506 | printk(KERN_NOTICE | ||
507 | "arcmsr%d: wait 'flush adapter cache' timeout \n" | ||
508 | , acb->host->host_no); | ||
509 | } | ||
510 | |||
511 | static void arcmsr_report_sense_info(struct CommandControlBlock *ccb) | ||
512 | { | ||
513 | struct scsi_cmnd *pcmd = ccb->pcmd; | ||
514 | struct SENSE_DATA *sensebuffer = (struct SENSE_DATA *)pcmd->sense_buffer; | ||
515 | |||
516 | pcmd->result = DID_OK << 16; | ||
517 | if (sensebuffer) { | ||
518 | int sense_data_length = | ||
519 | sizeof (struct SENSE_DATA) < sizeof (pcmd->sense_buffer) | ||
520 | ? sizeof (struct SENSE_DATA) : sizeof (pcmd->sense_buffer); | ||
521 | memset(sensebuffer, 0, sizeof (pcmd->sense_buffer)); | ||
522 | memcpy(sensebuffer, ccb->arcmsr_cdb.SenseData, sense_data_length); | ||
523 | sensebuffer->ErrorCode = SCSI_SENSE_CURRENT_ERRORS; | ||
524 | sensebuffer->Valid = 1; | ||
525 | } | ||
526 | } | ||
527 | |||
528 | static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb) | ||
529 | { | ||
530 | struct MessageUnit __iomem *reg = acb->pmu; | ||
531 | uint32_t Index; | ||
532 | uint8_t Retries = 0x00; | ||
533 | |||
534 | do { | ||
535 | for (Index = 0; Index < 100; Index++) { | ||
536 | if (readl(®->outbound_intstatus) | ||
537 | & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { | ||
538 | writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT | ||
539 | , ®->outbound_intstatus); | ||
540 | return 0x00; | ||
541 | } | ||
542 | msleep_interruptible(10); | ||
543 | }/*max 1 seconds*/ | ||
544 | } while (Retries++ < 20);/*max 20 sec*/ | ||
545 | return 0xff; | ||
546 | } | ||
547 | |||
548 | static void arcmsr_build_ccb(struct AdapterControlBlock *acb, | ||
549 | struct CommandControlBlock *ccb, struct scsi_cmnd *pcmd) | ||
550 | { | ||
551 | struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; | ||
552 | int8_t *psge = (int8_t *)&arcmsr_cdb->u; | ||
553 | uint32_t address_lo, address_hi; | ||
554 | int arccdbsize = 0x30; | ||
555 | |||
556 | ccb->pcmd = pcmd; | ||
557 | memset(arcmsr_cdb, 0, sizeof (struct ARCMSR_CDB)); | ||
558 | arcmsr_cdb->Bus = 0; | ||
559 | arcmsr_cdb->TargetID = pcmd->device->id; | ||
560 | arcmsr_cdb->LUN = pcmd->device->lun; | ||
561 | arcmsr_cdb->Function = 1; | ||
562 | arcmsr_cdb->CdbLength = (uint8_t)pcmd->cmd_len; | ||
563 | arcmsr_cdb->Context = (unsigned long)arcmsr_cdb; | ||
564 | memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len); | ||
565 | if (pcmd->use_sg) { | ||
566 | int length, sgcount, i, cdb_sgcount = 0; | ||
567 | struct scatterlist *sl; | ||
568 | |||
569 | /* Get Scatter Gather List from scsiport. */ | ||
570 | sl = (struct scatterlist *) pcmd->request_buffer; | ||
571 | sgcount = pci_map_sg(acb->pdev, sl, pcmd->use_sg, | ||
572 | pcmd->sc_data_direction); | ||
573 | /* map stor port SG list to our iop SG List. */ | ||
574 | for (i = 0; i < sgcount; i++) { | ||
575 | /* Get the physical address of the current data pointer */ | ||
576 | length = cpu_to_le32(sg_dma_len(sl)); | ||
577 | address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sl))); | ||
578 | address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sl))); | ||
579 | if (address_hi == 0) { | ||
580 | struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; | ||
581 | |||
582 | pdma_sg->address = address_lo; | ||
583 | pdma_sg->length = length; | ||
584 | psge += sizeof (struct SG32ENTRY); | ||
585 | arccdbsize += sizeof (struct SG32ENTRY); | ||
586 | } else { | ||
587 | struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; | ||
588 | |||
589 | pdma_sg->addresshigh = address_hi; | ||
590 | pdma_sg->address = address_lo; | ||
591 | pdma_sg->length = length|IS_SG64_ADDR; | ||
592 | psge += sizeof (struct SG64ENTRY); | ||
593 | arccdbsize += sizeof (struct SG64ENTRY); | ||
594 | } | ||
595 | sl++; | ||
596 | cdb_sgcount++; | ||
597 | } | ||
598 | arcmsr_cdb->sgcount = (uint8_t)cdb_sgcount; | ||
599 | arcmsr_cdb->DataLength = pcmd->request_bufflen; | ||
600 | if ( arccdbsize > 256) | ||
601 | arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; | ||
602 | } else if (pcmd->request_bufflen) { | ||
603 | dma_addr_t dma_addr; | ||
604 | dma_addr = pci_map_single(acb->pdev, pcmd->request_buffer, | ||
605 | pcmd->request_bufflen, pcmd->sc_data_direction); | ||
606 | pcmd->SCp.dma_handle = dma_addr; | ||
607 | address_lo = cpu_to_le32(dma_addr_lo32(dma_addr)); | ||
608 | address_hi = cpu_to_le32(dma_addr_hi32(dma_addr)); | ||
609 | if (address_hi == 0) { | ||
610 | struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; | ||
611 | pdma_sg->address = address_lo; | ||
612 | pdma_sg->length = pcmd->request_bufflen; | ||
613 | } else { | ||
614 | struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; | ||
615 | pdma_sg->addresshigh = address_hi; | ||
616 | pdma_sg->address = address_lo; | ||
617 | pdma_sg->length = pcmd->request_bufflen|IS_SG64_ADDR; | ||
618 | } | ||
619 | arcmsr_cdb->sgcount = 1; | ||
620 | arcmsr_cdb->DataLength = pcmd->request_bufflen; | ||
621 | } | ||
622 | if (pcmd->sc_data_direction == DMA_TO_DEVICE ) { | ||
623 | arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; | ||
624 | ccb->ccb_flags |= CCB_FLAG_WRITE; | ||
625 | } | ||
626 | } | ||
627 | |||
628 | static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb) | ||
629 | { | ||
630 | struct MessageUnit __iomem *reg = acb->pmu; | ||
631 | uint32_t cdb_shifted_phyaddr = ccb->cdb_shifted_phyaddr; | ||
632 | struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; | ||
633 | |||
634 | atomic_inc(&acb->ccboutstandingcount); | ||
635 | ccb->startdone = ARCMSR_CCB_START; | ||
636 | if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) | ||
637 | writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, | ||
638 | ®->inbound_queueport); | ||
639 | else | ||
640 | writel(cdb_shifted_phyaddr, ®->inbound_queueport); | ||
641 | } | ||
642 | |||
643 | void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb) | ||
644 | { | ||
645 | struct MessageUnit __iomem *reg = acb->pmu; | ||
646 | struct QBUFFER __iomem *pwbuffer = (struct QBUFFER __iomem *) ®->message_wbuffer; | ||
647 | uint8_t __iomem *iop_data = (uint8_t __iomem *) pwbuffer->data; | ||
648 | int32_t allxfer_len = 0; | ||
649 | |||
650 | if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { | ||
651 | acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); | ||
652 | while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) | ||
653 | && (allxfer_len < 124)) { | ||
654 | writeb(acb->wqbuffer[acb->wqbuf_firstindex], iop_data); | ||
655 | acb->wqbuf_firstindex++; | ||
656 | acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; | ||
657 | iop_data++; | ||
658 | allxfer_len++; | ||
659 | } | ||
660 | writel(allxfer_len, &pwbuffer->data_len); | ||
661 | writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK | ||
662 | , ®->inbound_doorbell); | ||
663 | } | ||
664 | } | ||
665 | |||
666 | static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) | ||
667 | { | ||
668 | struct MessageUnit __iomem *reg = acb->pmu; | ||
669 | |||
670 | acb->acb_flags &= ~ACB_F_MSG_START_BGRB; | ||
671 | writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0); | ||
672 | if (arcmsr_wait_msgint_ready(acb)) | ||
673 | printk(KERN_NOTICE | ||
674 | "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" | ||
675 | , acb->host->host_no); | ||
676 | } | ||
677 | |||
678 | static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) | ||
679 | { | ||
680 | dma_free_coherent(&acb->pdev->dev, | ||
681 | ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20, | ||
682 | acb->dma_coherent, | ||
683 | acb->dma_coherent_handle); | ||
684 | } | ||
685 | |||
686 | static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) | ||
687 | { | ||
688 | struct MessageUnit __iomem *reg = acb->pmu; | ||
689 | struct CommandControlBlock *ccb; | ||
690 | uint32_t flag_ccb, outbound_intstatus, outbound_doorbell; | ||
691 | |||
692 | outbound_intstatus = readl(®->outbound_intstatus) | ||
693 | & acb->outbound_int_enable; | ||
694 | writel(outbound_intstatus, ®->outbound_intstatus); | ||
695 | if (outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { | ||
696 | outbound_doorbell = readl(®->outbound_doorbell); | ||
697 | writel(outbound_doorbell, ®->outbound_doorbell); | ||
698 | if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { | ||
699 | struct QBUFFER __iomem * prbuffer = | ||
700 | (struct QBUFFER __iomem *) ®->message_rbuffer; | ||
701 | uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data; | ||
702 | int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; | ||
703 | |||
704 | rqbuf_lastindex = acb->rqbuf_lastindex; | ||
705 | rqbuf_firstindex = acb->rqbuf_firstindex; | ||
706 | iop_len = readl(&prbuffer->data_len); | ||
707 | my_empty_len = (rqbuf_firstindex - rqbuf_lastindex - 1) | ||
708 | &(ARCMSR_MAX_QBUFFER - 1); | ||
709 | if (my_empty_len >= iop_len) { | ||
710 | while (iop_len > 0) { | ||
711 | acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); | ||
712 | acb->rqbuf_lastindex++; | ||
713 | acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; | ||
714 | iop_data++; | ||
715 | iop_len--; | ||
716 | } | ||
717 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, | ||
718 | ®->inbound_doorbell); | ||
719 | } else | ||
720 | acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; | ||
721 | } | ||
722 | if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { | ||
723 | acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; | ||
724 | if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) { | ||
725 | struct QBUFFER __iomem * pwbuffer = | ||
726 | (struct QBUFFER __iomem *) ®->message_wbuffer; | ||
727 | uint8_t __iomem * iop_data = (uint8_t __iomem *) pwbuffer->data; | ||
728 | int32_t allxfer_len = 0; | ||
729 | |||
730 | acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); | ||
731 | while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) | ||
732 | && (allxfer_len < 124)) { | ||
733 | writeb(acb->wqbuffer[acb->wqbuf_firstindex], iop_data); | ||
734 | acb->wqbuf_firstindex++; | ||
735 | acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; | ||
736 | iop_data++; | ||
737 | allxfer_len++; | ||
738 | } | ||
739 | writel(allxfer_len, &pwbuffer->data_len); | ||
740 | writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK, | ||
741 | ®->inbound_doorbell); | ||
742 | } | ||
743 | if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) | ||
744 | acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; | ||
745 | } | ||
746 | } | ||
747 | if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { | ||
748 | int id, lun; | ||
749 | /* | ||
750 | **************************************************************** | ||
751 | ** areca cdb command done | ||
752 | **************************************************************** | ||
753 | */ | ||
754 | while (1) { | ||
755 | if ((flag_ccb = readl(®->outbound_queueport)) == 0xFFFFFFFF) | ||
756 | break;/*chip FIFO no ccb for completion already*/ | ||
757 | /* check if command done with no error*/ | ||
758 | ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + | ||
759 | (flag_ccb << 5)); | ||
760 | if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { | ||
761 | if (ccb->startdone == ARCMSR_CCB_ABORTED) { | ||
762 | struct scsi_cmnd *abortcmd=ccb->pcmd; | ||
763 | if (abortcmd) { | ||
764 | abortcmd->result |= DID_ABORT >> 16; | ||
765 | arcmsr_ccb_complete(ccb, 1); | ||
766 | printk(KERN_NOTICE | ||
767 | "arcmsr%d: ccb='0x%p' isr got aborted command \n" | ||
768 | , acb->host->host_no, ccb); | ||
769 | } | ||
770 | continue; | ||
771 | } | ||
772 | printk(KERN_NOTICE | ||
773 | "arcmsr%d: isr get an illegal ccb command done acb='0x%p'" | ||
774 | "ccb='0x%p' ccbacb='0x%p' startdone = 0x%x" | ||
775 | " ccboutstandingcount=%d \n" | ||
776 | , acb->host->host_no | ||
777 | , acb | ||
778 | , ccb | ||
779 | , ccb->acb | ||
780 | , ccb->startdone | ||
781 | , atomic_read(&acb->ccboutstandingcount)); | ||
782 | continue; | ||
783 | } | ||
784 | id = ccb->pcmd->device->id; | ||
785 | lun = ccb->pcmd->device->lun; | ||
786 | if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { | ||
787 | if (acb->devstate[id][lun] == ARECA_RAID_GONE) | ||
788 | acb->devstate[id][lun] = ARECA_RAID_GOOD; | ||
789 | ccb->pcmd->result = DID_OK << 16; | ||
790 | arcmsr_ccb_complete(ccb, 1); | ||
791 | } else { | ||
792 | switch(ccb->arcmsr_cdb.DeviceStatus) { | ||
793 | case ARCMSR_DEV_SELECT_TIMEOUT: { | ||
794 | acb->devstate[id][lun] = ARECA_RAID_GONE; | ||
795 | ccb->pcmd->result = DID_TIME_OUT << 16; | ||
796 | arcmsr_ccb_complete(ccb, 1); | ||
797 | } | ||
798 | break; | ||
799 | case ARCMSR_DEV_ABORTED: | ||
800 | case ARCMSR_DEV_INIT_FAIL: { | ||
801 | acb->devstate[id][lun] = ARECA_RAID_GONE; | ||
802 | ccb->pcmd->result = DID_BAD_TARGET << 16; | ||
803 | arcmsr_ccb_complete(ccb, 1); | ||
804 | } | ||
805 | break; | ||
806 | case ARCMSR_DEV_CHECK_CONDITION: { | ||
807 | acb->devstate[id][lun] = ARECA_RAID_GOOD; | ||
808 | arcmsr_report_sense_info(ccb); | ||
809 | arcmsr_ccb_complete(ccb, 1); | ||
810 | } | ||
811 | break; | ||
812 | default: | ||
813 | printk(KERN_NOTICE | ||
814 | "arcmsr%d: scsi id=%d lun=%d" | ||
815 | " isr get command error done," | ||
816 | "but got unknown DeviceStatus = 0x%x \n" | ||
817 | , acb->host->host_no | ||
818 | , id | ||
819 | , lun | ||
820 | , ccb->arcmsr_cdb.DeviceStatus); | ||
821 | acb->devstate[id][lun] = ARECA_RAID_GONE; | ||
822 | ccb->pcmd->result = DID_NO_CONNECT << 16; | ||
823 | arcmsr_ccb_complete(ccb, 1); | ||
824 | break; | ||
825 | } | ||
826 | } | ||
827 | }/*drain reply FIFO*/ | ||
828 | } | ||
829 | if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) | ||
830 | return IRQ_NONE; | ||
831 | return IRQ_HANDLED; | ||
832 | } | ||
833 | |||
834 | static void arcmsr_iop_parking(struct AdapterControlBlock *acb) | ||
835 | { | ||
836 | if (acb) { | ||
837 | /* stop adapter background rebuild */ | ||
838 | if (acb->acb_flags & ACB_F_MSG_START_BGRB) { | ||
839 | acb->acb_flags &= ~ACB_F_MSG_START_BGRB; | ||
840 | arcmsr_stop_adapter_bgrb(acb); | ||
841 | arcmsr_flush_adapter_cache(acb); | ||
842 | } | ||
843 | } | ||
844 | } | ||
845 | |||
846 | static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_cmnd *cmd) | ||
847 | { | ||
848 | struct MessageUnit __iomem *reg = acb->pmu; | ||
849 | struct CMD_MESSAGE_FIELD *pcmdmessagefld; | ||
850 | int retvalue = 0, transfer_len = 0; | ||
851 | char *buffer; | ||
852 | uint32_t controlcode = (uint32_t ) cmd->cmnd[5] << 24 | | ||
853 | (uint32_t ) cmd->cmnd[6] << 16 | | ||
854 | (uint32_t ) cmd->cmnd[7] << 8 | | ||
855 | (uint32_t ) cmd->cmnd[8]; | ||
856 | /* 4 bytes: Areca io control code */ | ||
857 | if (cmd->use_sg) { | ||
858 | struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer; | ||
859 | |||
860 | buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | ||
861 | if (cmd->use_sg > 1) { | ||
862 | retvalue = ARCMSR_MESSAGE_FAIL; | ||
863 | goto message_out; | ||
864 | } | ||
865 | transfer_len += sg->length; | ||
866 | } else { | ||
867 | buffer = cmd->request_buffer; | ||
868 | transfer_len = cmd->request_bufflen; | ||
869 | } | ||
870 | if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { | ||
871 | retvalue = ARCMSR_MESSAGE_FAIL; | ||
872 | goto message_out; | ||
873 | } | ||
874 | pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; | ||
875 | switch(controlcode) { | ||
876 | case ARCMSR_MESSAGE_READ_RQBUFFER: { | ||
877 | unsigned long *ver_addr; | ||
878 | dma_addr_t buf_handle; | ||
879 | uint8_t *pQbuffer, *ptmpQbuffer; | ||
880 | int32_t allxfer_len = 0; | ||
881 | |||
882 | ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); | ||
883 | if (!ver_addr) { | ||
884 | retvalue = ARCMSR_MESSAGE_FAIL; | ||
885 | goto message_out; | ||
886 | } | ||
887 | ptmpQbuffer = (uint8_t *) ver_addr; | ||
888 | while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) | ||
889 | && (allxfer_len < 1031)) { | ||
890 | pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; | ||
891 | memcpy(ptmpQbuffer, pQbuffer, 1); | ||
892 | acb->rqbuf_firstindex++; | ||
893 | acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; | ||
894 | ptmpQbuffer++; | ||
895 | allxfer_len++; | ||
896 | } | ||
897 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | ||
898 | struct QBUFFER __iomem * prbuffer = (struct QBUFFER __iomem *) | ||
899 | ®->message_rbuffer; | ||
900 | uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data; | ||
901 | int32_t iop_len; | ||
902 | |||
903 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | ||
904 | iop_len = readl(&prbuffer->data_len); | ||
905 | while (iop_len > 0) { | ||
906 | acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); | ||
907 | acb->rqbuf_lastindex++; | ||
908 | acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; | ||
909 | iop_data++; | ||
910 | iop_len--; | ||
911 | } | ||
912 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, | ||
913 | ®->inbound_doorbell); | ||
914 | } | ||
915 | memcpy(pcmdmessagefld->messagedatabuffer, | ||
916 | (uint8_t *)ver_addr, allxfer_len); | ||
917 | pcmdmessagefld->cmdmessage.Length = allxfer_len; | ||
918 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; | ||
919 | pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); | ||
920 | } | ||
921 | break; | ||
922 | case ARCMSR_MESSAGE_WRITE_WQBUFFER: { | ||
923 | unsigned long *ver_addr; | ||
924 | dma_addr_t buf_handle; | ||
925 | int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; | ||
926 | uint8_t *pQbuffer, *ptmpuserbuffer; | ||
927 | |||
928 | ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); | ||
929 | if (!ver_addr) { | ||
930 | retvalue = ARCMSR_MESSAGE_FAIL; | ||
931 | goto message_out; | ||
932 | } | ||
933 | ptmpuserbuffer = (uint8_t *)ver_addr; | ||
934 | user_len = pcmdmessagefld->cmdmessage.Length; | ||
935 | memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); | ||
936 | wqbuf_lastindex = acb->wqbuf_lastindex; | ||
937 | wqbuf_firstindex = acb->wqbuf_firstindex; | ||
938 | if (wqbuf_lastindex != wqbuf_firstindex) { | ||
939 | struct SENSE_DATA *sensebuffer = | ||
940 | (struct SENSE_DATA *)cmd->sense_buffer; | ||
941 | arcmsr_post_Qbuffer(acb); | ||
942 | /* has error report sensedata */ | ||
943 | sensebuffer->ErrorCode = 0x70; | ||
944 | sensebuffer->SenseKey = ILLEGAL_REQUEST; | ||
945 | sensebuffer->AdditionalSenseLength = 0x0A; | ||
946 | sensebuffer->AdditionalSenseCode = 0x20; | ||
947 | sensebuffer->Valid = 1; | ||
948 | retvalue = ARCMSR_MESSAGE_FAIL; | ||
949 | } else { | ||
950 | my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) | ||
951 | &(ARCMSR_MAX_QBUFFER - 1); | ||
952 | if (my_empty_len >= user_len) { | ||
953 | while (user_len > 0) { | ||
954 | pQbuffer = | ||
955 | &acb->wqbuffer[acb->wqbuf_lastindex]; | ||
956 | memcpy(pQbuffer, ptmpuserbuffer, 1); | ||
957 | acb->wqbuf_lastindex++; | ||
958 | acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; | ||
959 | ptmpuserbuffer++; | ||
960 | user_len--; | ||
961 | } | ||
962 | if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { | ||
963 | acb->acb_flags &= | ||
964 | ~ACB_F_MESSAGE_WQBUFFER_CLEARED; | ||
965 | arcmsr_post_Qbuffer(acb); | ||
966 | } | ||
967 | } else { | ||
968 | /* has error report sensedata */ | ||
969 | struct SENSE_DATA *sensebuffer = | ||
970 | (struct SENSE_DATA *)cmd->sense_buffer; | ||
971 | sensebuffer->ErrorCode = 0x70; | ||
972 | sensebuffer->SenseKey = ILLEGAL_REQUEST; | ||
973 | sensebuffer->AdditionalSenseLength = 0x0A; | ||
974 | sensebuffer->AdditionalSenseCode = 0x20; | ||
975 | sensebuffer->Valid = 1; | ||
976 | retvalue = ARCMSR_MESSAGE_FAIL; | ||
977 | } | ||
978 | } | ||
979 | pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); | ||
980 | } | ||
981 | break; | ||
982 | case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { | ||
983 | uint8_t *pQbuffer = acb->rqbuffer; | ||
984 | |||
985 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | ||
986 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | ||
987 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, | ||
988 | ®->inbound_doorbell); | ||
989 | } | ||
990 | acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; | ||
991 | acb->rqbuf_firstindex = 0; | ||
992 | acb->rqbuf_lastindex = 0; | ||
993 | memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); | ||
994 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
995 | ARCMSR_MESSAGE_RETURNCODE_OK; | ||
996 | } | ||
997 | break; | ||
998 | case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { | ||
999 | uint8_t *pQbuffer = acb->wqbuffer; | ||
1000 | |||
1001 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | ||
1002 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | ||
1003 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK | ||
1004 | , ®->inbound_doorbell); | ||
1005 | } | ||
1006 | acb->acb_flags |= | ||
1007 | (ACB_F_MESSAGE_WQBUFFER_CLEARED | | ||
1008 | ACB_F_MESSAGE_WQBUFFER_READED); | ||
1009 | acb->wqbuf_firstindex = 0; | ||
1010 | acb->wqbuf_lastindex = 0; | ||
1011 | memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); | ||
1012 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
1013 | ARCMSR_MESSAGE_RETURNCODE_OK; | ||
1014 | } | ||
1015 | break; | ||
1016 | case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { | ||
1017 | uint8_t *pQbuffer; | ||
1018 | |||
1019 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | ||
1020 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | ||
1021 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK | ||
1022 | , ®->inbound_doorbell); | ||
1023 | } | ||
1024 | acb->acb_flags |= | ||
1025 | (ACB_F_MESSAGE_WQBUFFER_CLEARED | ||
1026 | | ACB_F_MESSAGE_RQBUFFER_CLEARED | ||
1027 | | ACB_F_MESSAGE_WQBUFFER_READED); | ||
1028 | acb->rqbuf_firstindex = 0; | ||
1029 | acb->rqbuf_lastindex = 0; | ||
1030 | acb->wqbuf_firstindex = 0; | ||
1031 | acb->wqbuf_lastindex = 0; | ||
1032 | pQbuffer = acb->rqbuffer; | ||
1033 | memset(pQbuffer, 0, sizeof (struct QBUFFER)); | ||
1034 | pQbuffer = acb->wqbuffer; | ||
1035 | memset(pQbuffer, 0, sizeof (struct QBUFFER)); | ||
1036 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; | ||
1037 | } | ||
1038 | break; | ||
1039 | case ARCMSR_MESSAGE_RETURN_CODE_3F: { | ||
1040 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; | ||
1041 | } | ||
1042 | break; | ||
1043 | case ARCMSR_MESSAGE_SAY_HELLO: { | ||
1044 | int8_t * hello_string = "Hello! I am ARCMSR"; | ||
1045 | |||
1046 | memcpy(pcmdmessagefld->messagedatabuffer, hello_string | ||
1047 | , (int16_t)strlen(hello_string)); | ||
1048 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; | ||
1049 | } | ||
1050 | break; | ||
1051 | case ARCMSR_MESSAGE_SAY_GOODBYE: | ||
1052 | arcmsr_iop_parking(acb); | ||
1053 | break; | ||
1054 | case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: | ||
1055 | arcmsr_flush_adapter_cache(acb); | ||
1056 | break; | ||
1057 | default: | ||
1058 | retvalue = ARCMSR_MESSAGE_FAIL; | ||
1059 | } | ||
1060 | message_out: | ||
1061 | if (cmd->use_sg) { | ||
1062 | struct scatterlist *sg; | ||
1063 | |||
1064 | sg = (struct scatterlist *) cmd->request_buffer; | ||
1065 | kunmap_atomic(buffer - sg->offset, KM_IRQ0); | ||
1066 | } | ||
1067 | return retvalue; | ||
1068 | } | ||
1069 | |||
1070 | static struct CommandControlBlock *arcmsr_get_freeccb(struct AdapterControlBlock *acb) | ||
1071 | { | ||
1072 | struct list_head *head = &acb->ccb_free_list; | ||
1073 | struct CommandControlBlock *ccb = NULL; | ||
1074 | |||
1075 | if (!list_empty(head)) { | ||
1076 | ccb = list_entry(head->next, struct CommandControlBlock, list); | ||
1077 | list_del(head->next); | ||
1078 | } | ||
1079 | return ccb; | ||
1080 | } | ||
1081 | |||
1082 | static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, | ||
1083 | struct scsi_cmnd *cmd) | ||
1084 | { | ||
1085 | switch (cmd->cmnd[0]) { | ||
1086 | case INQUIRY: { | ||
1087 | unsigned char inqdata[36]; | ||
1088 | char *buffer; | ||
1089 | |||
1090 | if (cmd->device->lun) { | ||
1091 | cmd->result = (DID_TIME_OUT << 16); | ||
1092 | cmd->scsi_done(cmd); | ||
1093 | return; | ||
1094 | } | ||
1095 | inqdata[0] = TYPE_PROCESSOR; | ||
1096 | /* Periph Qualifier & Periph Dev Type */ | ||
1097 | inqdata[1] = 0; | ||
1098 | /* rem media bit & Dev Type Modifier */ | ||
1099 | inqdata[2] = 0; | ||
1100 | /* ISO,ECMA,& ANSI versions */ | ||
1101 | inqdata[4] = 31; | ||
1102 | /* length of additional data */ | ||
1103 | strncpy(&inqdata[8], "Areca ", 8); | ||
1104 | /* Vendor Identification */ | ||
1105 | strncpy(&inqdata[16], "RAID controller ", 16); | ||
1106 | /* Product Identification */ | ||
1107 | strncpy(&inqdata[32], "R001", 4); /* Product Revision */ | ||
1108 | if (cmd->use_sg) { | ||
1109 | struct scatterlist *sg; | ||
1110 | |||
1111 | sg = (struct scatterlist *) cmd->request_buffer; | ||
1112 | buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | ||
1113 | } else { | ||
1114 | buffer = cmd->request_buffer; | ||
1115 | } | ||
1116 | memcpy(buffer, inqdata, sizeof(inqdata)); | ||
1117 | if (cmd->use_sg) { | ||
1118 | struct scatterlist *sg; | ||
1119 | |||
1120 | sg = (struct scatterlist *) cmd->request_buffer; | ||
1121 | kunmap_atomic(buffer - sg->offset, KM_IRQ0); | ||
1122 | } | ||
1123 | cmd->scsi_done(cmd); | ||
1124 | } | ||
1125 | break; | ||
1126 | case WRITE_BUFFER: | ||
1127 | case READ_BUFFER: { | ||
1128 | if (arcmsr_iop_message_xfer(acb, cmd)) | ||
1129 | cmd->result = (DID_ERROR << 16); | ||
1130 | cmd->scsi_done(cmd); | ||
1131 | } | ||
1132 | break; | ||
1133 | default: | ||
1134 | cmd->scsi_done(cmd); | ||
1135 | } | ||
1136 | } | ||
1137 | |||
1138 | static int arcmsr_queue_command(struct scsi_cmnd *cmd, | ||
1139 | void (* done)(struct scsi_cmnd *)) | ||
1140 | { | ||
1141 | struct Scsi_Host *host = cmd->device->host; | ||
1142 | struct AdapterControlBlock *acb = | ||
1143 | (struct AdapterControlBlock *) host->hostdata; | ||
1144 | struct CommandControlBlock *ccb; | ||
1145 | int target = cmd->device->id; | ||
1146 | int lun = cmd->device->lun; | ||
1147 | |||
1148 | cmd->scsi_done = done; | ||
1149 | cmd->host_scribble = NULL; | ||
1150 | cmd->result = 0; | ||
1151 | if (acb->acb_flags & ACB_F_BUS_RESET) { | ||
1152 | printk(KERN_NOTICE "arcmsr%d: bus reset" | ||
1153 | " and return busy \n" | ||
1154 | , acb->host->host_no); | ||
1155 | return SCSI_MLQUEUE_HOST_BUSY; | ||
1156 | } | ||
1157 | if(target == 16) { | ||
1158 | /* virtual device for iop message transfer */ | ||
1159 | arcmsr_handle_virtual_command(acb, cmd); | ||
1160 | return 0; | ||
1161 | } | ||
1162 | if (acb->devstate[target][lun] == ARECA_RAID_GONE) { | ||
1163 | uint8_t block_cmd; | ||
1164 | |||
1165 | block_cmd = cmd->cmnd[0] & 0x0f; | ||
1166 | if (block_cmd == 0x08 || block_cmd == 0x0a) { | ||
1167 | printk(KERN_NOTICE | ||
1168 | "arcmsr%d: block 'read/write'" | ||
1169 | "command with gone raid volume" | ||
1170 | " Cmd=%2x, TargetId=%d, Lun=%d \n" | ||
1171 | , acb->host->host_no | ||
1172 | , cmd->cmnd[0] | ||
1173 | , target, lun); | ||
1174 | cmd->result = (DID_NO_CONNECT << 16); | ||
1175 | cmd->scsi_done(cmd); | ||
1176 | return 0; | ||
1177 | } | ||
1178 | } | ||
1179 | if (atomic_read(&acb->ccboutstandingcount) >= | ||
1180 | ARCMSR_MAX_OUTSTANDING_CMD) | ||
1181 | return SCSI_MLQUEUE_HOST_BUSY; | ||
1182 | |||
1183 | ccb = arcmsr_get_freeccb(acb); | ||
1184 | if (!ccb) | ||
1185 | return SCSI_MLQUEUE_HOST_BUSY; | ||
1186 | arcmsr_build_ccb(acb, ccb, cmd); | ||
1187 | arcmsr_post_ccb(acb, ccb); | ||
1188 | return 0; | ||
1189 | } | ||
1190 | |||
1191 | static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) | ||
1192 | { | ||
1193 | struct MessageUnit __iomem *reg = acb->pmu; | ||
1194 | char *acb_firm_model = acb->firm_model; | ||
1195 | char *acb_firm_version = acb->firm_version; | ||
1196 | char __iomem *iop_firm_model = (char __iomem *) ®->message_rwbuffer[15]; | ||
1197 | char __iomem *iop_firm_version = (char __iomem *) ®->message_rwbuffer[17]; | ||
1198 | int count; | ||
1199 | |||
1200 | writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); | ||
1201 | if (arcmsr_wait_msgint_ready(acb)) | ||
1202 | printk(KERN_NOTICE | ||
1203 | "arcmsr%d: wait " | ||
1204 | "'get adapter firmware miscellaneous data' timeout \n" | ||
1205 | , acb->host->host_no); | ||
1206 | count = 8; | ||
1207 | while (count) { | ||
1208 | *acb_firm_model = readb(iop_firm_model); | ||
1209 | acb_firm_model++; | ||
1210 | iop_firm_model++; | ||
1211 | count--; | ||
1212 | } | ||
1213 | count = 16; | ||
1214 | while (count) { | ||
1215 | *acb_firm_version = readb(iop_firm_version); | ||
1216 | acb_firm_version++; | ||
1217 | iop_firm_version++; | ||
1218 | count--; | ||
1219 | } | ||
1220 | printk(KERN_INFO | ||
1221 | "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n" | ||
1222 | , acb->host->host_no | ||
1223 | , acb->firm_version); | ||
1224 | acb->firm_request_len = readl(®->message_rwbuffer[1]); | ||
1225 | acb->firm_numbers_queue = readl(®->message_rwbuffer[2]); | ||
1226 | acb->firm_sdram_size = readl(®->message_rwbuffer[3]); | ||
1227 | acb->firm_hd_channels = readl(®->message_rwbuffer[4]); | ||
1228 | } | ||
1229 | |||
1230 | static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, | ||
1231 | struct CommandControlBlock *poll_ccb) | ||
1232 | { | ||
1233 | struct MessageUnit __iomem *reg = acb->pmu; | ||
1234 | struct CommandControlBlock *ccb; | ||
1235 | uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0; | ||
1236 | int id, lun; | ||
1237 | |||
1238 | polling_ccb_retry: | ||
1239 | poll_count++; | ||
1240 | outbound_intstatus = readl(®->outbound_intstatus) | ||
1241 | & acb->outbound_int_enable; | ||
1242 | writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/ | ||
1243 | while (1) { | ||
1244 | if ((flag_ccb = readl(®->outbound_queueport)) == 0xFFFFFFFF) { | ||
1245 | if (poll_ccb_done) | ||
1246 | break; | ||
1247 | else { | ||
1248 | msleep(25); | ||
1249 | if (poll_count > 100) | ||
1250 | break; | ||
1251 | goto polling_ccb_retry; | ||
1252 | } | ||
1253 | } | ||
1254 | ccb = (struct CommandControlBlock *) | ||
1255 | (acb->vir2phy_offset + (flag_ccb << 5)); | ||
1256 | if ((ccb->acb != acb) || | ||
1257 | (ccb->startdone != ARCMSR_CCB_START)) { | ||
1258 | if ((ccb->startdone == ARCMSR_CCB_ABORTED) || | ||
1259 | (ccb == poll_ccb)) { | ||
1260 | printk(KERN_NOTICE | ||
1261 | "arcmsr%d: scsi id=%d lun=%d ccb='0x%p'" | ||
1262 | " poll command abort successfully \n" | ||
1263 | , acb->host->host_no | ||
1264 | , ccb->pcmd->device->id | ||
1265 | , ccb->pcmd->device->lun | ||
1266 | , ccb); | ||
1267 | ccb->pcmd->result = DID_ABORT << 16; | ||
1268 | arcmsr_ccb_complete(ccb, 1); | ||
1269 | poll_ccb_done = 1; | ||
1270 | continue; | ||
1271 | } | ||
1272 | printk(KERN_NOTICE | ||
1273 | "arcmsr%d: polling get an illegal ccb" | ||
1274 | " command done ccb='0x%p'" | ||
1275 | "ccboutstandingcount=%d \n" | ||
1276 | , acb->host->host_no | ||
1277 | , ccb | ||
1278 | , atomic_read(&acb->ccboutstandingcount)); | ||
1279 | continue; | ||
1280 | } | ||
1281 | id = ccb->pcmd->device->id; | ||
1282 | lun = ccb->pcmd->device->lun; | ||
1283 | if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { | ||
1284 | if (acb->devstate[id][lun] == ARECA_RAID_GONE) | ||
1285 | acb->devstate[id][lun] = ARECA_RAID_GOOD; | ||
1286 | ccb->pcmd->result = DID_OK << 16; | ||
1287 | arcmsr_ccb_complete(ccb, 1); | ||
1288 | } else { | ||
1289 | switch(ccb->arcmsr_cdb.DeviceStatus) { | ||
1290 | case ARCMSR_DEV_SELECT_TIMEOUT: { | ||
1291 | acb->devstate[id][lun] = ARECA_RAID_GONE; | ||
1292 | ccb->pcmd->result = DID_TIME_OUT << 16; | ||
1293 | arcmsr_ccb_complete(ccb, 1); | ||
1294 | } | ||
1295 | break; | ||
1296 | case ARCMSR_DEV_ABORTED: | ||
1297 | case ARCMSR_DEV_INIT_FAIL: { | ||
1298 | acb->devstate[id][lun] = ARECA_RAID_GONE; | ||
1299 | ccb->pcmd->result = DID_BAD_TARGET << 16; | ||
1300 | arcmsr_ccb_complete(ccb, 1); | ||
1301 | } | ||
1302 | break; | ||
1303 | case ARCMSR_DEV_CHECK_CONDITION: { | ||
1304 | acb->devstate[id][lun] = ARECA_RAID_GOOD; | ||
1305 | arcmsr_report_sense_info(ccb); | ||
1306 | arcmsr_ccb_complete(ccb, 1); | ||
1307 | } | ||
1308 | break; | ||
1309 | default: | ||
1310 | printk(KERN_NOTICE | ||
1311 | "arcmsr%d: scsi id=%d lun=%d" | ||
1312 | " polling and getting command error done" | ||
1313 | "but got unknown DeviceStatus = 0x%x \n" | ||
1314 | , acb->host->host_no | ||
1315 | , id | ||
1316 | , lun | ||
1317 | , ccb->arcmsr_cdb.DeviceStatus); | ||
1318 | acb->devstate[id][lun] = ARECA_RAID_GONE; | ||
1319 | ccb->pcmd->result = DID_BAD_TARGET << 16; | ||
1320 | arcmsr_ccb_complete(ccb, 1); | ||
1321 | break; | ||
1322 | } | ||
1323 | } | ||
1324 | } | ||
1325 | } | ||
1326 | |||
1327 | static void arcmsr_iop_init(struct AdapterControlBlock *acb) | ||
1328 | { | ||
1329 | struct MessageUnit __iomem *reg = acb->pmu; | ||
1330 | uint32_t intmask_org, mask, outbound_doorbell, firmware_state = 0; | ||
1331 | |||
1332 | do { | ||
1333 | firmware_state = readl(®->outbound_msgaddr1); | ||
1334 | } while (!(firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK)); | ||
1335 | intmask_org = readl(®->outbound_intmask) | ||
1336 | | ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; | ||
1337 | arcmsr_get_firmware_spec(acb); | ||
1338 | |||
1339 | acb->acb_flags |= ACB_F_MSG_START_BGRB; | ||
1340 | writel(ARCMSR_INBOUND_MESG0_START_BGRB, ®->inbound_msgaddr0); | ||
1341 | if (arcmsr_wait_msgint_ready(acb)) { | ||
1342 | printk(KERN_NOTICE "arcmsr%d: " | ||
1343 | "wait 'start adapter background rebulid' timeout\n", | ||
1344 | acb->host->host_no); | ||
1345 | } | ||
1346 | |||
1347 | outbound_doorbell = readl(®->outbound_doorbell); | ||
1348 | writel(outbound_doorbell, ®->outbound_doorbell); | ||
1349 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); | ||
1350 | mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | ||
1351 | | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); | ||
1352 | writel(intmask_org & mask, ®->outbound_intmask); | ||
1353 | acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; | ||
1354 | acb->acb_flags |= ACB_F_IOP_INITED; | ||
1355 | } | ||
1356 | |||
1357 | static void arcmsr_iop_reset(struct AdapterControlBlock *acb) | ||
1358 | { | ||
1359 | struct MessageUnit __iomem *reg = acb->pmu; | ||
1360 | struct CommandControlBlock *ccb; | ||
1361 | uint32_t intmask_org; | ||
1362 | int i = 0; | ||
1363 | |||
1364 | if (atomic_read(&acb->ccboutstandingcount) != 0) { | ||
1365 | /* talk to iop 331 outstanding command aborted */ | ||
1366 | arcmsr_abort_allcmd(acb); | ||
1367 | /* wait for 3 sec for all command aborted*/ | ||
1368 | msleep_interruptible(3000); | ||
1369 | /* disable all outbound interrupt */ | ||
1370 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
1371 | /* clear all outbound posted Q */ | ||
1372 | for (i = 0; i < ARCMSR_MAX_OUTSTANDING_CMD; i++) | ||
1373 | readl(®->outbound_queueport); | ||
1374 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { | ||
1375 | ccb = acb->pccb_pool[i]; | ||
1376 | if ((ccb->startdone == ARCMSR_CCB_START) || | ||
1377 | (ccb->startdone == ARCMSR_CCB_ABORTED)) { | ||
1378 | ccb->startdone = ARCMSR_CCB_ABORTED; | ||
1379 | ccb->pcmd->result = DID_ABORT << 16; | ||
1380 | arcmsr_ccb_complete(ccb, 1); | ||
1381 | } | ||
1382 | } | ||
1383 | /* enable all outbound interrupt */ | ||
1384 | arcmsr_enable_outbound_ints(acb, intmask_org); | ||
1385 | } | ||
1386 | atomic_set(&acb->ccboutstandingcount, 0); | ||
1387 | } | ||
1388 | |||
1389 | static int arcmsr_bus_reset(struct scsi_cmnd *cmd) | ||
1390 | { | ||
1391 | struct AdapterControlBlock *acb = | ||
1392 | (struct AdapterControlBlock *)cmd->device->host->hostdata; | ||
1393 | int i; | ||
1394 | |||
1395 | acb->num_resets++; | ||
1396 | acb->acb_flags |= ACB_F_BUS_RESET; | ||
1397 | for (i = 0; i < 400; i++) { | ||
1398 | if (!atomic_read(&acb->ccboutstandingcount)) | ||
1399 | break; | ||
1400 | arcmsr_interrupt(acb); | ||
1401 | msleep(25); | ||
1402 | } | ||
1403 | arcmsr_iop_reset(acb); | ||
1404 | acb->acb_flags &= ~ACB_F_BUS_RESET; | ||
1405 | return SUCCESS; | ||
1406 | } | ||
1407 | |||
1408 | static void arcmsr_abort_one_cmd(struct AdapterControlBlock *acb, | ||
1409 | struct CommandControlBlock *ccb) | ||
1410 | { | ||
1411 | u32 intmask; | ||
1412 | |||
1413 | ccb->startdone = ARCMSR_CCB_ABORTED; | ||
1414 | |||
1415 | /* | ||
1416 | ** Wait for 3 sec for all command done. | ||
1417 | */ | ||
1418 | msleep_interruptible(3000); | ||
1419 | |||
1420 | intmask = arcmsr_disable_outbound_ints(acb); | ||
1421 | arcmsr_polling_ccbdone(acb, ccb); | ||
1422 | arcmsr_enable_outbound_ints(acb, intmask); | ||
1423 | } | ||
1424 | |||
1425 | static int arcmsr_abort(struct scsi_cmnd *cmd) | ||
1426 | { | ||
1427 | struct AdapterControlBlock *acb = | ||
1428 | (struct AdapterControlBlock *)cmd->device->host->hostdata; | ||
1429 | int i = 0; | ||
1430 | |||
1431 | printk(KERN_NOTICE | ||
1432 | "arcmsr%d: abort device command of scsi id=%d lun=%d \n", | ||
1433 | acb->host->host_no, cmd->device->id, cmd->device->lun); | ||
1434 | acb->num_aborts++; | ||
1435 | |||
1436 | /* | ||
1437 | ************************************************ | ||
1438 | ** the all interrupt service routine is locked | ||
1439 | ** we need to handle it as soon as possible and exit | ||
1440 | ************************************************ | ||
1441 | */ | ||
1442 | if (!atomic_read(&acb->ccboutstandingcount)) | ||
1443 | return SUCCESS; | ||
1444 | |||
1445 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { | ||
1446 | struct CommandControlBlock *ccb = acb->pccb_pool[i]; | ||
1447 | if (ccb->startdone == ARCMSR_CCB_START && ccb->pcmd == cmd) { | ||
1448 | arcmsr_abort_one_cmd(acb, ccb); | ||
1449 | break; | ||
1450 | } | ||
1451 | } | ||
1452 | |||
1453 | return SUCCESS; | ||
1454 | } | ||
1455 | |||
1456 | static const char *arcmsr_info(struct Scsi_Host *host) | ||
1457 | { | ||
1458 | struct AdapterControlBlock *acb = | ||
1459 | (struct AdapterControlBlock *) host->hostdata; | ||
1460 | static char buf[256]; | ||
1461 | char *type; | ||
1462 | int raid6 = 1; | ||
1463 | |||
1464 | switch (acb->pdev->device) { | ||
1465 | case PCI_DEVICE_ID_ARECA_1110: | ||
1466 | case PCI_DEVICE_ID_ARECA_1210: | ||
1467 | raid6 = 0; | ||
1468 | /*FALLTHRU*/ | ||
1469 | case PCI_DEVICE_ID_ARECA_1120: | ||
1470 | case PCI_DEVICE_ID_ARECA_1130: | ||
1471 | case PCI_DEVICE_ID_ARECA_1160: | ||
1472 | case PCI_DEVICE_ID_ARECA_1170: | ||
1473 | case PCI_DEVICE_ID_ARECA_1220: | ||
1474 | case PCI_DEVICE_ID_ARECA_1230: | ||
1475 | case PCI_DEVICE_ID_ARECA_1260: | ||
1476 | case PCI_DEVICE_ID_ARECA_1270: | ||
1477 | case PCI_DEVICE_ID_ARECA_1280: | ||
1478 | type = "SATA"; | ||
1479 | break; | ||
1480 | case PCI_DEVICE_ID_ARECA_1380: | ||
1481 | case PCI_DEVICE_ID_ARECA_1381: | ||
1482 | case PCI_DEVICE_ID_ARECA_1680: | ||
1483 | case PCI_DEVICE_ID_ARECA_1681: | ||
1484 | type = "SAS"; | ||
1485 | break; | ||
1486 | default: | ||
1487 | type = "X-TYPE"; | ||
1488 | break; | ||
1489 | } | ||
1490 | sprintf(buf, "Areca %s Host Adapter RAID Controller%s\n %s", | ||
1491 | type, raid6 ? "( RAID6 capable)" : "", | ||
1492 | ARCMSR_DRIVER_VERSION); | ||
1493 | return buf; | ||
1494 | } | ||
1495 | |||
1496 | |||
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index e1337339cac..45806336ce0 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c | |||
@@ -46,7 +46,6 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver"); | |||
46 | 46 | ||
47 | #include <linux/stat.h> | 47 | #include <linux/stat.h> |
48 | #include <linux/slab.h> /* for kmalloc() */ | 48 | #include <linux/slab.h> /* for kmalloc() */ |
49 | #include <linux/config.h> /* for CONFIG_PCI */ | ||
50 | #include <linux/pci.h> /* for PCI support */ | 49 | #include <linux/pci.h> /* for PCI support */ |
51 | #include <linux/proc_fs.h> | 50 | #include <linux/proc_fs.h> |
52 | #include <linux/blkdev.h> | 51 | #include <linux/blkdev.h> |
diff --git a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c index 7f891023aa1..c4e16c0775d 100644 --- a/drivers/scsi/fcal.c +++ b/drivers/scsi/fcal.c | |||
@@ -248,8 +248,7 @@ int fcal_proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t of | |||
248 | if (scd->id == target) { | 248 | if (scd->id == target) { |
249 | SPRINTF (" [AL-PA: %02x, Id: %02d, Port WWN: %08x%08x, Node WWN: %08x%08x] ", | 249 | SPRINTF (" [AL-PA: %02x, Id: %02d, Port WWN: %08x%08x, Node WWN: %08x%08x] ", |
250 | alpa, target, u1[0], u1[1], u2[0], u2[1]); | 250 | alpa, target, u1[0], u1[1], u2[0], u2[1]); |
251 | SPRINTF ("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ? | 251 | SPRINTF ("%s ", scsi_device_type(scd->type)); |
252 | scsi_device_types[(short) scd->type] : "Unknown device"); | ||
253 | 252 | ||
254 | for (j = 0; (j < 8) && (scd->vendor[j] >= 0x20); j++) | 253 | for (j = 0; (j < 8) && (scd->vendor[j] >= 0x20); j++) |
255 | SPRINTF ("%c", scd->vendor[j]); | 254 | SPRINTF ("%c", scd->vendor[j]); |
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 67f1100f310..cdd893bb4e2 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c | |||
@@ -811,7 +811,6 @@ static int generic_NCR5380_proc_info(struct Scsi_Host *scsi_ptr, char *buffer, c | |||
811 | struct NCR5380_hostdata *hostdata; | 811 | struct NCR5380_hostdata *hostdata; |
812 | #ifdef NCR5380_STATS | 812 | #ifdef NCR5380_STATS |
813 | struct scsi_device *dev; | 813 | struct scsi_device *dev; |
814 | extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE]; | ||
815 | #endif | 814 | #endif |
816 | 815 | ||
817 | NCR5380_setup(scsi_ptr); | 816 | NCR5380_setup(scsi_ptr); |
@@ -851,7 +850,7 @@ static int generic_NCR5380_proc_info(struct Scsi_Host *scsi_ptr, char *buffer, c | |||
851 | long tr = hostdata->time_read[dev->id] / HZ; | 850 | long tr = hostdata->time_read[dev->id] / HZ; |
852 | long tw = hostdata->time_write[dev->id] / HZ; | 851 | long tw = hostdata->time_write[dev->id] / HZ; |
853 | 852 | ||
854 | PRINTP(" T:%d %s " ANDP dev->id ANDP(dev->type < MAX_SCSI_DEVICE_CODE) ? scsi_device_types[(int) dev->type] : "Unknown"); | 853 | PRINTP(" T:%d %s " ANDP dev->id ANDP scsi_device_type(dev->type)); |
855 | for (i = 0; i < 8; i++) | 854 | for (i = 0; i < 8; i++) |
856 | if (dev->vendor[i] >= 0x20) | 855 | if (dev->vendor[i] >= 0x20) |
857 | *(buffer + (len++)) = dev->vendor[i]; | 856 | *(buffer + (len++)) = dev->vendor[i]; |
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index dfcb96f3e60..f244d4f6597 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
@@ -487,7 +487,9 @@ EXPORT_SYMBOL(scsi_is_host_device); | |||
487 | * @work: Work to queue for execution. | 487 | * @work: Work to queue for execution. |
488 | * | 488 | * |
489 | * Return value: | 489 | * Return value: |
490 | * 0 on success / != 0 for error | 490 | * 1 - work queued for execution |
491 | * 0 - work is already queued | ||
492 | * -EINVAL - work queue doesn't exist | ||
491 | **/ | 493 | **/ |
492 | int scsi_queue_work(struct Scsi_Host *shost, struct work_struct *work) | 494 | int scsi_queue_work(struct Scsi_Host *shost, struct work_struct *work) |
493 | { | 495 | { |
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index bcb3444f1dc..28bfb8f9f81 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c | |||
@@ -15,7 +15,6 @@ | |||
15 | * | 15 | * |
16 | * For more information, visit http://www.highpoint-tech.com | 16 | * For more information, visit http://www.highpoint-tech.com |
17 | */ | 17 | */ |
18 | #include <linux/config.h> | ||
19 | #include <linux/module.h> | 18 | #include <linux/module.h> |
20 | #include <linux/types.h> | 19 | #include <linux/types.h> |
21 | #include <linux/string.h> | 20 | #include <linux/string.h> |
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 01080b3acf5..7ed4eef8347 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -175,6 +175,8 @@ struct ipr_error_table_t ipr_error_table[] = { | |||
175 | "Qualified success"}, | 175 | "Qualified success"}, |
176 | {0x01080000, 1, 1, | 176 | {0x01080000, 1, 1, |
177 | "FFFE: Soft device bus error recovered by the IOA"}, | 177 | "FFFE: Soft device bus error recovered by the IOA"}, |
178 | {0x01088100, 0, 1, | ||
179 | "4101: Soft device bus fabric error"}, | ||
178 | {0x01170600, 0, 1, | 180 | {0x01170600, 0, 1, |
179 | "FFF9: Device sector reassign successful"}, | 181 | "FFF9: Device sector reassign successful"}, |
180 | {0x01170900, 0, 1, | 182 | {0x01170900, 0, 1, |
@@ -225,6 +227,8 @@ struct ipr_error_table_t ipr_error_table[] = { | |||
225 | "3109: IOA timed out a device command"}, | 227 | "3109: IOA timed out a device command"}, |
226 | {0x04088000, 0, 0, | 228 | {0x04088000, 0, 0, |
227 | "3120: SCSI bus is not operational"}, | 229 | "3120: SCSI bus is not operational"}, |
230 | {0x04088100, 0, 1, | ||
231 | "4100: Hard device bus fabric error"}, | ||
228 | {0x04118000, 0, 1, | 232 | {0x04118000, 0, 1, |
229 | "9000: IOA reserved area data check"}, | 233 | "9000: IOA reserved area data check"}, |
230 | {0x04118100, 0, 1, | 234 | {0x04118100, 0, 1, |
@@ -273,6 +277,14 @@ struct ipr_error_table_t ipr_error_table[] = { | |||
273 | "9091: Incorrect hardware configuration change has been detected"}, | 277 | "9091: Incorrect hardware configuration change has been detected"}, |
274 | {0x04678000, 0, 1, | 278 | {0x04678000, 0, 1, |
275 | "9073: Invalid multi-adapter configuration"}, | 279 | "9073: Invalid multi-adapter configuration"}, |
280 | {0x04678100, 0, 1, | ||
281 | "4010: Incorrect connection between cascaded expanders"}, | ||
282 | {0x04678200, 0, 1, | ||
283 | "4020: Connections exceed IOA design limits"}, | ||
284 | {0x04678300, 0, 1, | ||
285 | "4030: Incorrect multipath connection"}, | ||
286 | {0x04679000, 0, 1, | ||
287 | "4110: Unsupported enclosure function"}, | ||
276 | {0x046E0000, 0, 1, | 288 | {0x046E0000, 0, 1, |
277 | "FFF4: Command to logical unit failed"}, | 289 | "FFF4: Command to logical unit failed"}, |
278 | {0x05240000, 1, 0, | 290 | {0x05240000, 1, 0, |
@@ -297,6 +309,8 @@ struct ipr_error_table_t ipr_error_table[] = { | |||
297 | "9031: Array protection temporarily suspended, protection resuming"}, | 309 | "9031: Array protection temporarily suspended, protection resuming"}, |
298 | {0x06040600, 0, 1, | 310 | {0x06040600, 0, 1, |
299 | "9040: Array protection temporarily suspended, protection resuming"}, | 311 | "9040: Array protection temporarily suspended, protection resuming"}, |
312 | {0x06288000, 0, 1, | ||
313 | "3140: Device bus not ready to ready transition"}, | ||
300 | {0x06290000, 0, 1, | 314 | {0x06290000, 0, 1, |
301 | "FFFB: SCSI bus was reset"}, | 315 | "FFFB: SCSI bus was reset"}, |
302 | {0x06290500, 0, 0, | 316 | {0x06290500, 0, 0, |
@@ -319,6 +333,16 @@ struct ipr_error_table_t ipr_error_table[] = { | |||
319 | "3150: SCSI bus configuration error"}, | 333 | "3150: SCSI bus configuration error"}, |
320 | {0x06678100, 0, 1, | 334 | {0x06678100, 0, 1, |
321 | "9074: Asymmetric advanced function disk configuration"}, | 335 | "9074: Asymmetric advanced function disk configuration"}, |
336 | {0x06678300, 0, 1, | ||
337 | "4040: Incomplete multipath connection between IOA and enclosure"}, | ||
338 | {0x06678400, 0, 1, | ||
339 | "4041: Incomplete multipath connection between enclosure and device"}, | ||
340 | {0x06678500, 0, 1, | ||
341 | "9075: Incomplete multipath connection between IOA and remote IOA"}, | ||
342 | {0x06678600, 0, 1, | ||
343 | "9076: Configuration error, missing remote IOA"}, | ||
344 | {0x06679100, 0, 1, | ||
345 | "4050: Enclosure does not support a required multipath function"}, | ||
322 | {0x06690200, 0, 1, | 346 | {0x06690200, 0, 1, |
323 | "9041: Array protection temporarily suspended"}, | 347 | "9041: Array protection temporarily suspended"}, |
324 | {0x06698200, 0, 1, | 348 | {0x06698200, 0, 1, |
@@ -331,6 +355,10 @@ struct ipr_error_table_t ipr_error_table[] = { | |||
331 | "9072: Link not operational transition"}, | 355 | "9072: Link not operational transition"}, |
332 | {0x066B8200, 0, 1, | 356 | {0x066B8200, 0, 1, |
333 | "9032: Array exposed but still protected"}, | 357 | "9032: Array exposed but still protected"}, |
358 | {0x066B9100, 0, 1, | ||
359 | "4061: Multipath redundancy level got better"}, | ||
360 | {0x066B9200, 0, 1, | ||
361 | "4060: Multipath redundancy level got worse"}, | ||
334 | {0x07270000, 0, 0, | 362 | {0x07270000, 0, 0, |
335 | "Failure due to other device"}, | 363 | "Failure due to other device"}, |
336 | {0x07278000, 0, 1, | 364 | {0x07278000, 0, 1, |
@@ -4099,8 +4127,7 @@ static int ipr_get_autosense(struct ipr_cmnd *ipr_cmd) | |||
4099 | { | 4127 | { |
4100 | struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; | 4128 | struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; |
4101 | 4129 | ||
4102 | if ((be32_to_cpu(ioasa->ioasc_specific) & | 4130 | if ((be32_to_cpu(ioasa->ioasc_specific) & IPR_AUTOSENSE_VALID) == 0) |
4103 | (IPR_ADDITIONAL_STATUS_FMT | IPR_AUTOSENSE_VALID)) == 0) | ||
4104 | return 0; | 4131 | return 0; |
4105 | 4132 | ||
4106 | memcpy(ipr_cmd->scsi_cmd->sense_buffer, ioasa->auto_sense.data, | 4133 | memcpy(ipr_cmd->scsi_cmd->sense_buffer, ioasa->auto_sense.data, |
@@ -4190,7 +4217,8 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg, | |||
4190 | case IPR_IOASC_NR_INIT_CMD_REQUIRED: | 4217 | case IPR_IOASC_NR_INIT_CMD_REQUIRED: |
4191 | break; | 4218 | break; |
4192 | default: | 4219 | default: |
4193 | scsi_cmd->result |= (DID_ERROR << 16); | 4220 | if (IPR_IOASC_SENSE_KEY(ioasc) > RECOVERED_ERROR) |
4221 | scsi_cmd->result |= (DID_ERROR << 16); | ||
4194 | if (!ipr_is_vset_device(res) && !ipr_is_naca_model(res)) | 4222 | if (!ipr_is_vset_device(res) && !ipr_is_naca_model(res)) |
4195 | res->needs_sync_complete = 1; | 4223 | res->needs_sync_complete = 1; |
4196 | break; | 4224 | break; |
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 1ad24df69d7..11eaff52432 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h | |||
@@ -36,8 +36,8 @@ | |||
36 | /* | 36 | /* |
37 | * Literals | 37 | * Literals |
38 | */ | 38 | */ |
39 | #define IPR_DRIVER_VERSION "2.1.3" | 39 | #define IPR_DRIVER_VERSION "2.1.4" |
40 | #define IPR_DRIVER_DATE "(March 29, 2006)" | 40 | #define IPR_DRIVER_DATE "(August 2, 2006)" |
41 | 41 | ||
42 | /* | 42 | /* |
43 | * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding | 43 | * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding |
@@ -45,6 +45,7 @@ | |||
45 | * This can be adjusted at runtime through sysfs device attributes. | 45 | * This can be adjusted at runtime through sysfs device attributes. |
46 | */ | 46 | */ |
47 | #define IPR_MAX_CMD_PER_LUN 6 | 47 | #define IPR_MAX_CMD_PER_LUN 6 |
48 | #define IPR_MAX_CMD_PER_ATA_LUN 1 | ||
48 | 49 | ||
49 | /* | 50 | /* |
50 | * IPR_NUM_BASE_CMD_BLKS: This defines the maximum number of | 51 | * IPR_NUM_BASE_CMD_BLKS: This defines the maximum number of |
@@ -106,7 +107,7 @@ | |||
106 | #define IPR_IOA_BUS 0xff | 107 | #define IPR_IOA_BUS 0xff |
107 | #define IPR_IOA_TARGET 0xff | 108 | #define IPR_IOA_TARGET 0xff |
108 | #define IPR_IOA_LUN 0xff | 109 | #define IPR_IOA_LUN 0xff |
109 | #define IPR_MAX_NUM_BUSES 8 | 110 | #define IPR_MAX_NUM_BUSES 16 |
110 | #define IPR_MAX_BUS_TO_SCAN IPR_MAX_NUM_BUSES | 111 | #define IPR_MAX_BUS_TO_SCAN IPR_MAX_NUM_BUSES |
111 | 112 | ||
112 | #define IPR_NUM_RESET_RELOAD_RETRIES 3 | 113 | #define IPR_NUM_RESET_RELOAD_RETRIES 3 |
@@ -145,6 +146,7 @@ | |||
145 | #define IPR_LUN_RESET 0x40 | 146 | #define IPR_LUN_RESET 0x40 |
146 | #define IPR_TARGET_RESET 0x20 | 147 | #define IPR_TARGET_RESET 0x20 |
147 | #define IPR_BUS_RESET 0x10 | 148 | #define IPR_BUS_RESET 0x10 |
149 | #define IPR_ATA_PHY_RESET 0x80 | ||
148 | #define IPR_ID_HOST_RR_Q 0xC4 | 150 | #define IPR_ID_HOST_RR_Q 0xC4 |
149 | #define IPR_QUERY_IOA_CONFIG 0xC5 | 151 | #define IPR_QUERY_IOA_CONFIG 0xC5 |
150 | #define IPR_CANCEL_ALL_REQUESTS 0xCE | 152 | #define IPR_CANCEL_ALL_REQUESTS 0xCE |
@@ -295,7 +297,11 @@ struct ipr_std_inq_data { | |||
295 | }__attribute__ ((packed)); | 297 | }__attribute__ ((packed)); |
296 | 298 | ||
297 | struct ipr_config_table_entry { | 299 | struct ipr_config_table_entry { |
298 | u8 service_level; | 300 | u8 proto; |
301 | #define IPR_PROTO_SATA 0x02 | ||
302 | #define IPR_PROTO_SATA_ATAPI 0x03 | ||
303 | #define IPR_PROTO_SAS_STP 0x06 | ||
304 | #define IPR_PROTO_SAS_STP_ATAPI 0x07 | ||
299 | u8 array_id; | 305 | u8 array_id; |
300 | u8 flags; | 306 | u8 flags; |
301 | #define IPR_IS_IOA_RESOURCE 0x80 | 307 | #define IPR_IS_IOA_RESOURCE 0x80 |
@@ -307,6 +313,7 @@ struct ipr_config_table_entry { | |||
307 | #define IPR_SUBTYPE_AF_DASD 0 | 313 | #define IPR_SUBTYPE_AF_DASD 0 |
308 | #define IPR_SUBTYPE_GENERIC_SCSI 1 | 314 | #define IPR_SUBTYPE_GENERIC_SCSI 1 |
309 | #define IPR_SUBTYPE_VOLUME_SET 2 | 315 | #define IPR_SUBTYPE_VOLUME_SET 2 |
316 | #define IPR_SUBTYPE_GENERIC_ATA 4 | ||
310 | 317 | ||
311 | #define IPR_QUEUEING_MODEL(res) ((((res)->cfgte.flags) & 0x70) >> 4) | 318 | #define IPR_QUEUEING_MODEL(res) ((((res)->cfgte.flags) & 0x70) >> 4) |
312 | #define IPR_QUEUE_FROZEN_MODEL 0 | 319 | #define IPR_QUEUE_FROZEN_MODEL 0 |
@@ -350,6 +357,7 @@ struct ipr_cmd_pkt { | |||
350 | #define IPR_RQTYPE_SCSICDB 0x00 | 357 | #define IPR_RQTYPE_SCSICDB 0x00 |
351 | #define IPR_RQTYPE_IOACMD 0x01 | 358 | #define IPR_RQTYPE_IOACMD 0x01 |
352 | #define IPR_RQTYPE_HCAM 0x02 | 359 | #define IPR_RQTYPE_HCAM 0x02 |
360 | #define IPR_RQTYPE_ATA_PASSTHRU 0x04 | ||
353 | 361 | ||
354 | u8 luntar_luntrn; | 362 | u8 luntar_luntrn; |
355 | 363 | ||
@@ -373,6 +381,37 @@ struct ipr_cmd_pkt { | |||
373 | __be16 timeout; | 381 | __be16 timeout; |
374 | }__attribute__ ((packed, aligned(4))); | 382 | }__attribute__ ((packed, aligned(4))); |
375 | 383 | ||
384 | struct ipr_ioarcb_ata_regs { | ||
385 | u8 flags; | ||
386 | #define IPR_ATA_FLAG_PACKET_CMD 0x80 | ||
387 | #define IPR_ATA_FLAG_XFER_TYPE_DMA 0x40 | ||
388 | #define IPR_ATA_FLAG_STATUS_ON_GOOD_COMPLETION 0x20 | ||
389 | u8 reserved[3]; | ||
390 | |||
391 | __be16 data; | ||
392 | u8 feature; | ||
393 | u8 nsect; | ||
394 | u8 lbal; | ||
395 | u8 lbam; | ||
396 | u8 lbah; | ||
397 | u8 device; | ||
398 | u8 command; | ||
399 | u8 reserved2[3]; | ||
400 | u8 hob_feature; | ||
401 | u8 hob_nsect; | ||
402 | u8 hob_lbal; | ||
403 | u8 hob_lbam; | ||
404 | u8 hob_lbah; | ||
405 | u8 ctl; | ||
406 | }__attribute__ ((packed, aligned(4))); | ||
407 | |||
408 | struct ipr_ioarcb_add_data { | ||
409 | union { | ||
410 | struct ipr_ioarcb_ata_regs regs; | ||
411 | __be32 add_cmd_parms[10]; | ||
412 | }u; | ||
413 | }__attribute__ ((packed, aligned(4))); | ||
414 | |||
376 | /* IOA Request Control Block 128 bytes */ | 415 | /* IOA Request Control Block 128 bytes */ |
377 | struct ipr_ioarcb { | 416 | struct ipr_ioarcb { |
378 | __be32 ioarcb_host_pci_addr; | 417 | __be32 ioarcb_host_pci_addr; |
@@ -397,7 +436,7 @@ struct ipr_ioarcb { | |||
397 | struct ipr_cmd_pkt cmd_pkt; | 436 | struct ipr_cmd_pkt cmd_pkt; |
398 | 437 | ||
399 | __be32 add_cmd_parms_len; | 438 | __be32 add_cmd_parms_len; |
400 | __be32 add_cmd_parms[10]; | 439 | struct ipr_ioarcb_add_data add_data; |
401 | }__attribute__((packed, aligned (4))); | 440 | }__attribute__((packed, aligned (4))); |
402 | 441 | ||
403 | struct ipr_ioadl_desc { | 442 | struct ipr_ioadl_desc { |
@@ -433,6 +472,21 @@ struct ipr_ioasa_gpdd { | |||
433 | __be32 ioa_data[2]; | 472 | __be32 ioa_data[2]; |
434 | }__attribute__((packed, aligned (4))); | 473 | }__attribute__((packed, aligned (4))); |
435 | 474 | ||
475 | struct ipr_ioasa_gata { | ||
476 | u8 error; | ||
477 | u8 nsect; /* Interrupt reason */ | ||
478 | u8 lbal; | ||
479 | u8 lbam; | ||
480 | u8 lbah; | ||
481 | u8 device; | ||
482 | u8 status; | ||
483 | u8 alt_status; /* ATA CTL */ | ||
484 | u8 hob_nsect; | ||
485 | u8 hob_lbal; | ||
486 | u8 hob_lbam; | ||
487 | u8 hob_lbah; | ||
488 | }__attribute__((packed, aligned (4))); | ||
489 | |||
436 | struct ipr_auto_sense { | 490 | struct ipr_auto_sense { |
437 | __be16 auto_sense_len; | 491 | __be16 auto_sense_len; |
438 | __be16 ioa_data_len; | 492 | __be16 ioa_data_len; |
@@ -466,6 +520,7 @@ struct ipr_ioasa { | |||
466 | __be32 ioasc_specific; /* status code specific field */ | 520 | __be32 ioasc_specific; /* status code specific field */ |
467 | #define IPR_ADDITIONAL_STATUS_FMT 0x80000000 | 521 | #define IPR_ADDITIONAL_STATUS_FMT 0x80000000 |
468 | #define IPR_AUTOSENSE_VALID 0x40000000 | 522 | #define IPR_AUTOSENSE_VALID 0x40000000 |
523 | #define IPR_ATA_DEVICE_WAS_RESET 0x20000000 | ||
469 | #define IPR_IOASC_SPECIFIC_MASK 0x00ffffff | 524 | #define IPR_IOASC_SPECIFIC_MASK 0x00ffffff |
470 | #define IPR_FIELD_POINTER_VALID (0x80000000 >> 8) | 525 | #define IPR_FIELD_POINTER_VALID (0x80000000 >> 8) |
471 | #define IPR_FIELD_POINTER_MASK 0x0000ffff | 526 | #define IPR_FIELD_POINTER_MASK 0x0000ffff |
@@ -474,6 +529,7 @@ struct ipr_ioasa { | |||
474 | struct ipr_ioasa_vset vset; | 529 | struct ipr_ioasa_vset vset; |
475 | struct ipr_ioasa_af_dasd dasd; | 530 | struct ipr_ioasa_af_dasd dasd; |
476 | struct ipr_ioasa_gpdd gpdd; | 531 | struct ipr_ioasa_gpdd gpdd; |
532 | struct ipr_ioasa_gata gata; | ||
477 | } u; | 533 | } u; |
478 | 534 | ||
479 | struct ipr_auto_sense auto_sense; | 535 | struct ipr_auto_sense auto_sense; |
@@ -1308,6 +1364,22 @@ static inline int ipr_is_scsi_disk(struct ipr_resource_entry *res) | |||
1308 | } | 1364 | } |
1309 | 1365 | ||
1310 | /** | 1366 | /** |
1367 | * ipr_is_gata - Determine if a resource is a generic ATA resource | ||
1368 | * @res: resource entry struct | ||
1369 | * | ||
1370 | * Return value: | ||
1371 | * 1 if GATA / 0 if not GATA | ||
1372 | **/ | ||
1373 | static inline int ipr_is_gata(struct ipr_resource_entry *res) | ||
1374 | { | ||
1375 | if (!ipr_is_ioa_resource(res) && | ||
1376 | IPR_RES_SUBTYPE(res) == IPR_SUBTYPE_GENERIC_ATA) | ||
1377 | return 1; | ||
1378 | else | ||
1379 | return 0; | ||
1380 | } | ||
1381 | |||
1382 | /** | ||
1311 | * ipr_is_naca_model - Determine if a resource is using NACA queueing model | 1383 | * ipr_is_naca_model - Determine if a resource is using NACA queueing model |
1312 | * @res: resource entry struct | 1384 | * @res: resource entry struct |
1313 | * | 1385 | * |
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 29f59345305..2c34af99627 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c | |||
@@ -32,7 +32,6 @@ | |||
32 | * | 32 | * |
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include <linux/config.h> | ||
36 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
37 | #include <scsi/scsi.h> | 36 | #include <scsi/scsi.h> |
38 | #include <scsi/scsi_host.h> | 37 | #include <scsi/scsi_host.h> |
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 76edbb639d3..ccb0055ac73 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c | |||
@@ -2822,9 +2822,7 @@ mega_print_inquiry(char *page, char *scsi_inq) | |||
2822 | 2822 | ||
2823 | i = scsi_inq[0] & 0x1f; | 2823 | i = scsi_inq[0] & 0x1f; |
2824 | 2824 | ||
2825 | len += sprintf(page+len, " Type: %s ", | 2825 | len += sprintf(page+len, " Type: %s ", scsi_device_type(i)); |
2826 | i < MAX_SCSI_DEVICE_CODE ? scsi_device_types[i] : | ||
2827 | "Unknown "); | ||
2828 | 2826 | ||
2829 | len += sprintf(page+len, | 2827 | len += sprintf(page+len, |
2830 | " ANSI SCSI revision: %02x", scsi_inq[2] & 0x07); | 2828 | " ANSI SCSI revision: %02x", scsi_inq[2] & 0x07); |
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index cd982c877da..266b3910846 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c | |||
@@ -330,6 +330,21 @@ static struct device_attribute *megaraid_sdev_attrs[] = { | |||
330 | NULL, | 330 | NULL, |
331 | }; | 331 | }; |
332 | 332 | ||
333 | /** | ||
334 | * megaraid_change_queue_depth - Change the device's queue depth | ||
335 | * @sdev: scsi device struct | ||
336 | * @qdepth: depth to set | ||
337 | * | ||
338 | * Return value: | ||
339 | * actual depth set | ||
340 | **/ | ||
341 | static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth) | ||
342 | { | ||
343 | if (qdepth > MBOX_MAX_SCSI_CMDS) | ||
344 | qdepth = MBOX_MAX_SCSI_CMDS; | ||
345 | scsi_adjust_queue_depth(sdev, 0, qdepth); | ||
346 | return sdev->queue_depth; | ||
347 | } | ||
333 | 348 | ||
334 | /* | 349 | /* |
335 | * Scsi host template for megaraid unified driver | 350 | * Scsi host template for megaraid unified driver |
@@ -343,6 +358,7 @@ static struct scsi_host_template megaraid_template_g = { | |||
343 | .eh_device_reset_handler = megaraid_reset_handler, | 358 | .eh_device_reset_handler = megaraid_reset_handler, |
344 | .eh_bus_reset_handler = megaraid_reset_handler, | 359 | .eh_bus_reset_handler = megaraid_reset_handler, |
345 | .eh_host_reset_handler = megaraid_reset_handler, | 360 | .eh_host_reset_handler = megaraid_reset_handler, |
361 | .change_queue_depth = megaraid_change_queue_depth, | ||
346 | .use_clustering = ENABLE_CLUSTERING, | 362 | .use_clustering = ENABLE_CLUSTERING, |
347 | .sdev_attrs = megaraid_sdev_attrs, | 363 | .sdev_attrs = megaraid_sdev_attrs, |
348 | .shost_attrs = megaraid_shost_attrs, | 364 | .shost_attrs = megaraid_shost_attrs, |
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index a8c9627a15c..4cab5b534b2 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c | |||
@@ -53,31 +53,15 @@ MODULE_DESCRIPTION("LSI Logic MegaRAID SAS Driver"); | |||
53 | */ | 53 | */ |
54 | static struct pci_device_id megasas_pci_table[] = { | 54 | static struct pci_device_id megasas_pci_table[] = { |
55 | 55 | ||
56 | { | 56 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064R)}, |
57 | PCI_VENDOR_ID_LSI_LOGIC, | 57 | /* xscale IOP */ |
58 | PCI_DEVICE_ID_LSI_SAS1064R, /* xscale IOP */ | 58 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078R)}, |
59 | PCI_ANY_ID, | 59 | /* ppc IOP */ |
60 | PCI_ANY_ID, | 60 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)}, |
61 | }, | 61 | /* xscale IOP, vega */ |
62 | { | 62 | {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)}, |
63 | PCI_VENDOR_ID_LSI_LOGIC, | 63 | /* xscale IOP */ |
64 | PCI_DEVICE_ID_LSI_SAS1078R, /* ppc IOP */ | 64 | {} |
65 | PCI_ANY_ID, | ||
66 | PCI_ANY_ID, | ||
67 | }, | ||
68 | { | ||
69 | PCI_VENDOR_ID_LSI_LOGIC, | ||
70 | PCI_DEVICE_ID_LSI_VERDE_ZCR, /* xscale IOP, vega */ | ||
71 | PCI_ANY_ID, | ||
72 | PCI_ANY_ID, | ||
73 | }, | ||
74 | { | ||
75 | PCI_VENDOR_ID_DELL, | ||
76 | PCI_DEVICE_ID_DELL_PERC5, /* xscale IOP */ | ||
77 | PCI_ANY_ID, | ||
78 | PCI_ANY_ID, | ||
79 | }, | ||
80 | {0} /* Terminating entry */ | ||
81 | }; | 65 | }; |
82 | 66 | ||
83 | MODULE_DEVICE_TABLE(pci, megasas_pci_table); | 67 | MODULE_DEVICE_TABLE(pci, megasas_pci_table); |
@@ -2854,7 +2838,7 @@ static int __init megasas_init(void) | |||
2854 | /* | 2838 | /* |
2855 | * Register ourselves as PCI hotplug module | 2839 | * Register ourselves as PCI hotplug module |
2856 | */ | 2840 | */ |
2857 | rval = pci_module_init(&megasas_pci_driver); | 2841 | rval = pci_register_driver(&megasas_pci_driver); |
2858 | 2842 | ||
2859 | if (rval) { | 2843 | if (rval) { |
2860 | printk(KERN_DEBUG "megasas: PCI hotplug regisration failed \n"); | 2844 | printk(KERN_DEBUG "megasas: PCI hotplug regisration failed \n"); |
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index b332caddd5b..94df671d776 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -96,24 +96,40 @@ unsigned int scsi_logging_level; | |||
96 | EXPORT_SYMBOL(scsi_logging_level); | 96 | EXPORT_SYMBOL(scsi_logging_level); |
97 | #endif | 97 | #endif |
98 | 98 | ||
99 | const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] = { | 99 | static const char *const scsi_device_types[] = { |
100 | "Direct-Access ", | 100 | "Direct access ", |
101 | "Sequential-Access", | 101 | "Sequential access", |
102 | "Printer ", | 102 | "Printer ", |
103 | "Processor ", | 103 | "Processor ", |
104 | "WORM ", | 104 | "WORM ", |
105 | "CD-ROM ", | 105 | "CD/DVD ", |
106 | "Scanner ", | 106 | "Scanner ", |
107 | "Optical Device ", | 107 | "Optical memory ", |
108 | "Medium Changer ", | 108 | "Media changer ", |
109 | "Communications ", | 109 | "Communications ", |
110 | "Unknown ", | 110 | "ASC IT8 ", |
111 | "Unknown ", | 111 | "ASC IT8 ", |
112 | "RAID ", | 112 | "RAID ", |
113 | "Enclosure ", | 113 | "Enclosure ", |
114 | "Direct-Access-RBC", | 114 | "Direct access RBC", |
115 | "Optical card ", | ||
116 | "Bridge controller", | ||
117 | "Object storage ", | ||
118 | "Automation/Drive ", | ||
115 | }; | 119 | }; |
116 | EXPORT_SYMBOL(scsi_device_types); | 120 | |
121 | const char * scsi_device_type(unsigned type) | ||
122 | { | ||
123 | if (type == 0x1e) | ||
124 | return "Well-known LUN "; | ||
125 | if (type == 0x1f) | ||
126 | return "No Device "; | ||
127 | if (type > ARRAY_SIZE(scsi_device_types)) | ||
128 | return "Unknown "; | ||
129 | return scsi_device_types[type]; | ||
130 | } | ||
131 | |||
132 | EXPORT_SYMBOL(scsi_device_type); | ||
117 | 133 | ||
118 | struct scsi_host_cmd_pool { | 134 | struct scsi_host_cmd_pool { |
119 | kmem_cache_t *slab; | 135 | kmem_cache_t *slab; |
diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h index f51e466893e..d5a55fae60e 100644 --- a/drivers/scsi/scsi.h +++ b/drivers/scsi/scsi.h | |||
@@ -20,8 +20,6 @@ | |||
20 | #ifndef _SCSI_H | 20 | #ifndef _SCSI_H |
21 | #define _SCSI_H | 21 | #define _SCSI_H |
22 | 22 | ||
23 | #include <linux/config.h> /* for CONFIG_SCSI_LOGGING */ | ||
24 | |||
25 | #include <scsi/scsi_cmnd.h> | 23 | #include <scsi/scsi_cmnd.h> |
26 | #include <scsi/scsi_device.h> | 24 | #include <scsi/scsi_device.h> |
27 | #include <scsi/scsi_eh.h> | 25 | #include <scsi/scsi_eh.h> |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 077c1c69121..d6743b959a7 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -551,7 +551,15 @@ static void scsi_run_queue(struct request_queue *q) | |||
551 | list_del_init(&sdev->starved_entry); | 551 | list_del_init(&sdev->starved_entry); |
552 | spin_unlock_irqrestore(shost->host_lock, flags); | 552 | spin_unlock_irqrestore(shost->host_lock, flags); |
553 | 553 | ||
554 | blk_run_queue(sdev->request_queue); | 554 | |
555 | if (test_bit(QUEUE_FLAG_REENTER, &q->queue_flags) && | ||
556 | !test_and_set_bit(QUEUE_FLAG_REENTER, | ||
557 | &sdev->request_queue->queue_flags)) { | ||
558 | blk_run_queue(sdev->request_queue); | ||
559 | clear_bit(QUEUE_FLAG_REENTER, | ||
560 | &sdev->request_queue->queue_flags); | ||
561 | } else | ||
562 | blk_run_queue(sdev->request_queue); | ||
555 | 563 | ||
556 | spin_lock_irqsave(shost->host_lock, flags); | 564 | spin_lock_irqsave(shost->host_lock, flags); |
557 | if (unlikely(!list_empty(&sdev->starved_entry))) | 565 | if (unlikely(!list_empty(&sdev->starved_entry))) |
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index 55200e4fdf1..524a5f7a519 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c | |||
@@ -178,9 +178,7 @@ static int proc_print_scsidevice(struct device *dev, void *data) | |||
178 | 178 | ||
179 | seq_printf(s, "\n"); | 179 | seq_printf(s, "\n"); |
180 | 180 | ||
181 | seq_printf(s, " Type: %s ", | 181 | seq_printf(s, " Type: %s ", scsi_device_type(sdev->type)); |
182 | sdev->type < MAX_SCSI_DEVICE_CODE ? | ||
183 | scsi_device_types[(int) sdev->type] : "Unknown "); | ||
184 | seq_printf(s, " ANSI" | 182 | seq_printf(s, " ANSI" |
185 | " SCSI revision: %02x", (sdev->scsi_level - 1) ? | 183 | " SCSI revision: %02x", (sdev->scsi_level - 1) ? |
186 | sdev->scsi_level - 1 : 1); | 184 | sdev->scsi_level - 1 : 1); |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 1bd92b9b46d..a24d3461fc7 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -134,59 +134,6 @@ static void scsi_unlock_floptical(struct scsi_device *sdev, | |||
134 | } | 134 | } |
135 | 135 | ||
136 | /** | 136 | /** |
137 | * print_inquiry - printk the inquiry information | ||
138 | * @inq_result: printk this SCSI INQUIRY | ||
139 | * | ||
140 | * Description: | ||
141 | * printk the vendor, model, and other information found in the | ||
142 | * INQUIRY data in @inq_result. | ||
143 | * | ||
144 | * Notes: | ||
145 | * Remove this, and replace with a hotplug event that logs any | ||
146 | * relevant information. | ||
147 | **/ | ||
148 | static void print_inquiry(unsigned char *inq_result) | ||
149 | { | ||
150 | int i; | ||
151 | |||
152 | printk(KERN_NOTICE " Vendor: "); | ||
153 | for (i = 8; i < 16; i++) | ||
154 | if (inq_result[i] >= 0x20 && i < inq_result[4] + 5) | ||
155 | printk("%c", inq_result[i]); | ||
156 | else | ||
157 | printk(" "); | ||
158 | |||
159 | printk(" Model: "); | ||
160 | for (i = 16; i < 32; i++) | ||
161 | if (inq_result[i] >= 0x20 && i < inq_result[4] + 5) | ||
162 | printk("%c", inq_result[i]); | ||
163 | else | ||
164 | printk(" "); | ||
165 | |||
166 | printk(" Rev: "); | ||
167 | for (i = 32; i < 36; i++) | ||
168 | if (inq_result[i] >= 0x20 && i < inq_result[4] + 5) | ||
169 | printk("%c", inq_result[i]); | ||
170 | else | ||
171 | printk(" "); | ||
172 | |||
173 | printk("\n"); | ||
174 | |||
175 | i = inq_result[0] & 0x1f; | ||
176 | |||
177 | printk(KERN_NOTICE " Type: %s ", | ||
178 | i < | ||
179 | MAX_SCSI_DEVICE_CODE ? scsi_device_types[i] : | ||
180 | "Unknown "); | ||
181 | printk(" ANSI SCSI revision: %02x", | ||
182 | inq_result[2] & 0x07); | ||
183 | if ((inq_result[2] & 0x07) == 1 && (inq_result[3] & 0x0f) == 1) | ||
184 | printk(" CCS\n"); | ||
185 | else | ||
186 | printk("\n"); | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * scsi_alloc_sdev - allocate and setup a scsi_Device | 137 | * scsi_alloc_sdev - allocate and setup a scsi_Device |
191 | * | 138 | * |
192 | * Description: | 139 | * Description: |
@@ -653,9 +600,8 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) | |||
653 | if (*bflags & BLIST_ISROM) { | 600 | if (*bflags & BLIST_ISROM) { |
654 | /* | 601 | /* |
655 | * It would be better to modify sdev->type, and set | 602 | * It would be better to modify sdev->type, and set |
656 | * sdev->removable, but then the print_inquiry() output | 603 | * sdev->removable; this can now be done since |
657 | * would not show TYPE_ROM; if print_inquiry() is removed | 604 | * print_inquiry has gone away. |
658 | * the issue goes away. | ||
659 | */ | 605 | */ |
660 | inq_result[0] = TYPE_ROM; | 606 | inq_result[0] = TYPE_ROM; |
661 | inq_result[1] |= 0x80; /* removable */ | 607 | inq_result[1] |= 0x80; /* removable */ |
@@ -684,8 +630,6 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) | |||
684 | printk(KERN_INFO "scsi: unknown device type %d\n", sdev->type); | 630 | printk(KERN_INFO "scsi: unknown device type %d\n", sdev->type); |
685 | } | 631 | } |
686 | 632 | ||
687 | print_inquiry(inq_result); | ||
688 | |||
689 | /* | 633 | /* |
690 | * For a peripheral qualifier (PQ) value of 1 (001b), the SCSI | 634 | * For a peripheral qualifier (PQ) value of 1 (001b), the SCSI |
691 | * spec says: The device server is capable of supporting the | 635 | * spec says: The device server is capable of supporting the |
@@ -715,6 +659,12 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) | |||
715 | if (inq_result[7] & 0x10) | 659 | if (inq_result[7] & 0x10) |
716 | sdev->sdtr = 1; | 660 | sdev->sdtr = 1; |
717 | 661 | ||
662 | sdev_printk(KERN_NOTICE, sdev, "%s %.8s %.16s %.4s PQ: %d " | ||
663 | "ANSI: %d%s\n", scsi_device_type(sdev->type), | ||
664 | sdev->vendor, sdev->model, sdev->rev, | ||
665 | sdev->inq_periph_qual, inq_result[2] & 0x07, | ||
666 | (inq_result[3] & 0x0f) == 1 ? " CCS" : ""); | ||
667 | |||
718 | /* | 668 | /* |
719 | * End sysfs code. | 669 | * End sysfs code. |
720 | */ | 670 | */ |
@@ -943,11 +893,26 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
943 | } | 893 | } |
944 | 894 | ||
945 | /* | 895 | /* |
946 | * Non-standard SCSI targets may set the PDT to 0x1f (unknown or | 896 | * Some targets may set slight variations of PQ and PDT to signal |
947 | * no device type) instead of using the Peripheral Qualifier to | 897 | * that no LUN is present, so don't add sdev in these cases. |
948 | * indicate that no LUN is present. For example, USB UFI does this. | 898 | * Two specific examples are: |
899 | * 1) NetApp targets: return PQ=1, PDT=0x1f | ||
900 | * 2) USB UFI: returns PDT=0x1f, with the PQ bits being "reserved" | ||
901 | * in the UFI 1.0 spec (we cannot rely on reserved bits). | ||
902 | * | ||
903 | * References: | ||
904 | * 1) SCSI SPC-3, pp. 145-146 | ||
905 | * PQ=1: "A peripheral device having the specified peripheral | ||
906 | * device type is not connected to this logical unit. However, the | ||
907 | * device server is capable of supporting the specified peripheral | ||
908 | * device type on this logical unit." | ||
909 | * PDT=0x1f: "Unknown or no device type" | ||
910 | * 2) USB UFI 1.0, p. 20 | ||
911 | * PDT=00h Direct-access device (floppy) | ||
912 | * PDT=1Fh none (no FDD connected to the requested logical unit) | ||
949 | */ | 913 | */ |
950 | if (starget->pdt_1f_for_no_lun && (result[0] & 0x1f) == 0x1f) { | 914 | if (((result[0] >> 5) == 1 || starget->pdt_1f_for_no_lun) && |
915 | (result[0] & 0x1f) == 0x1f) { | ||
951 | SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO | 916 | SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO |
952 | "scsi scan: peripheral device type" | 917 | "scsi scan: peripheral device type" |
953 | " of 31, no device added\n")); | 918 | " of 31, no device added\n")); |
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index b03aa85108e..79d31ca2b74 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
@@ -301,8 +301,6 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev, | |||
301 | fc_host->supported_classes = FC_COS_UNSPECIFIED; | 301 | fc_host->supported_classes = FC_COS_UNSPECIFIED; |
302 | memset(fc_host->supported_fc4s, 0, | 302 | memset(fc_host->supported_fc4s, 0, |
303 | sizeof(fc_host->supported_fc4s)); | 303 | sizeof(fc_host->supported_fc4s)); |
304 | memset(fc_host->symbolic_name, 0, | ||
305 | sizeof(fc_host->symbolic_name)); | ||
306 | fc_host->supported_speeds = FC_PORTSPEED_UNKNOWN; | 304 | fc_host->supported_speeds = FC_PORTSPEED_UNKNOWN; |
307 | fc_host->maxframe_size = -1; | 305 | fc_host->maxframe_size = -1; |
308 | memset(fc_host->serial_number, 0, | 306 | memset(fc_host->serial_number, 0, |
@@ -315,6 +313,8 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev, | |||
315 | sizeof(fc_host->active_fc4s)); | 313 | sizeof(fc_host->active_fc4s)); |
316 | fc_host->speed = FC_PORTSPEED_UNKNOWN; | 314 | fc_host->speed = FC_PORTSPEED_UNKNOWN; |
317 | fc_host->fabric_name = -1; | 315 | fc_host->fabric_name = -1; |
316 | memset(fc_host->symbolic_name, 0, sizeof(fc_host->symbolic_name)); | ||
317 | memset(fc_host->system_hostname, 0, sizeof(fc_host->system_hostname)); | ||
318 | 318 | ||
319 | fc_host->tgtid_bind_type = FC_TGTID_BIND_BY_WWPN; | 319 | fc_host->tgtid_bind_type = FC_TGTID_BIND_BY_WWPN; |
320 | 320 | ||
@@ -688,6 +688,25 @@ store_fc_host_##field(struct class_device *cdev, const char *buf, \ | |||
688 | return count; \ | 688 | return count; \ |
689 | } | 689 | } |
690 | 690 | ||
691 | #define fc_host_store_str_function(field, slen) \ | ||
692 | static ssize_t \ | ||
693 | store_fc_host_##field(struct class_device *cdev, const char *buf, \ | ||
694 | size_t count) \ | ||
695 | { \ | ||
696 | struct Scsi_Host *shost = transport_class_to_shost(cdev); \ | ||
697 | struct fc_internal *i = to_fc_internal(shost->transportt); \ | ||
698 | unsigned int cnt=count; \ | ||
699 | \ | ||
700 | /* count may include a LF at end of string */ \ | ||
701 | if (buf[cnt-1] == '\n') \ | ||
702 | cnt--; \ | ||
703 | if (cnt > ((slen) - 1)) \ | ||
704 | return -EINVAL; \ | ||
705 | memcpy(fc_host_##field(shost), buf, cnt); \ | ||
706 | i->f->set_host_##field(shost); \ | ||
707 | return count; \ | ||
708 | } | ||
709 | |||
691 | #define fc_host_rd_attr(field, format_string, sz) \ | 710 | #define fc_host_rd_attr(field, format_string, sz) \ |
692 | fc_host_show_function(field, format_string, sz, ) \ | 711 | fc_host_show_function(field, format_string, sz, ) \ |
693 | static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \ | 712 | static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \ |
@@ -815,7 +834,6 @@ fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long); | |||
815 | fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long); | 834 | fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long); |
816 | fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20, | 835 | fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20, |
817 | unsigned long long); | 836 | unsigned long long); |
818 | fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1)); | ||
819 | fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20); | 837 | fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20); |
820 | fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1)); | 838 | fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1)); |
821 | 839 | ||
@@ -858,6 +876,13 @@ fc_host_rd_attr(port_id, "0x%06x\n", 20); | |||
858 | fc_host_rd_enum_attr(port_type, FC_PORTTYPE_MAX_NAMELEN); | 876 | fc_host_rd_enum_attr(port_type, FC_PORTTYPE_MAX_NAMELEN); |
859 | fc_host_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN); | 877 | fc_host_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN); |
860 | fc_host_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long); | 878 | fc_host_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long); |
879 | fc_host_rd_attr(symbolic_name, "%s\n", FC_SYMBOLIC_NAME_SIZE + 1); | ||
880 | |||
881 | fc_private_host_show_function(system_hostname, "%s\n", | ||
882 | FC_SYMBOLIC_NAME_SIZE + 1, ) | ||
883 | fc_host_store_str_function(system_hostname, FC_SYMBOLIC_NAME_SIZE) | ||
884 | static FC_CLASS_DEVICE_ATTR(host, system_hostname, S_IRUGO | S_IWUSR, | ||
885 | show_fc_host_system_hostname, store_fc_host_system_hostname); | ||
861 | 886 | ||
862 | 887 | ||
863 | /* Private Host Attributes */ | 888 | /* Private Host Attributes */ |
@@ -1223,7 +1248,6 @@ fc_attach_transport(struct fc_function_template *ft) | |||
1223 | SETUP_HOST_ATTRIBUTE_RD(permanent_port_name); | 1248 | SETUP_HOST_ATTRIBUTE_RD(permanent_port_name); |
1224 | SETUP_HOST_ATTRIBUTE_RD(supported_classes); | 1249 | SETUP_HOST_ATTRIBUTE_RD(supported_classes); |
1225 | SETUP_HOST_ATTRIBUTE_RD(supported_fc4s); | 1250 | SETUP_HOST_ATTRIBUTE_RD(supported_fc4s); |
1226 | SETUP_HOST_ATTRIBUTE_RD(symbolic_name); | ||
1227 | SETUP_HOST_ATTRIBUTE_RD(supported_speeds); | 1251 | SETUP_HOST_ATTRIBUTE_RD(supported_speeds); |
1228 | SETUP_HOST_ATTRIBUTE_RD(maxframe_size); | 1252 | SETUP_HOST_ATTRIBUTE_RD(maxframe_size); |
1229 | SETUP_HOST_ATTRIBUTE_RD(serial_number); | 1253 | SETUP_HOST_ATTRIBUTE_RD(serial_number); |
@@ -1234,6 +1258,8 @@ fc_attach_transport(struct fc_function_template *ft) | |||
1234 | SETUP_HOST_ATTRIBUTE_RD(active_fc4s); | 1258 | SETUP_HOST_ATTRIBUTE_RD(active_fc4s); |
1235 | SETUP_HOST_ATTRIBUTE_RD(speed); | 1259 | SETUP_HOST_ATTRIBUTE_RD(speed); |
1236 | SETUP_HOST_ATTRIBUTE_RD(fabric_name); | 1260 | SETUP_HOST_ATTRIBUTE_RD(fabric_name); |
1261 | SETUP_HOST_ATTRIBUTE_RD(symbolic_name); | ||
1262 | SETUP_HOST_ATTRIBUTE_RW(system_hostname); | ||
1237 | 1263 | ||
1238 | /* Transport-managed attributes */ | 1264 | /* Transport-managed attributes */ |
1239 | SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type); | 1265 | SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type); |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 4eae06b08cf..47faf43fde1 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -2004,6 +2004,23 @@ | |||
2004 | #define PCI_DEVICE_ID_ALTIMA_AC9100 0x03ea | 2004 | #define PCI_DEVICE_ID_ALTIMA_AC9100 0x03ea |
2005 | #define PCI_DEVICE_ID_ALTIMA_AC1003 0x03eb | 2005 | #define PCI_DEVICE_ID_ALTIMA_AC1003 0x03eb |
2006 | 2006 | ||
2007 | #define PCI_VENDOR_ID_ARECA 0x17d3 | ||
2008 | #define PCI_DEVICE_ID_ARECA_1110 0x1110 | ||
2009 | #define PCI_DEVICE_ID_ARECA_1120 0x1120 | ||
2010 | #define PCI_DEVICE_ID_ARECA_1130 0x1130 | ||
2011 | #define PCI_DEVICE_ID_ARECA_1160 0x1160 | ||
2012 | #define PCI_DEVICE_ID_ARECA_1170 0x1170 | ||
2013 | #define PCI_DEVICE_ID_ARECA_1210 0x1210 | ||
2014 | #define PCI_DEVICE_ID_ARECA_1220 0x1220 | ||
2015 | #define PCI_DEVICE_ID_ARECA_1230 0x1230 | ||
2016 | #define PCI_DEVICE_ID_ARECA_1260 0x1260 | ||
2017 | #define PCI_DEVICE_ID_ARECA_1270 0x1270 | ||
2018 | #define PCI_DEVICE_ID_ARECA_1280 0x1280 | ||
2019 | #define PCI_DEVICE_ID_ARECA_1380 0x1380 | ||
2020 | #define PCI_DEVICE_ID_ARECA_1381 0x1381 | ||
2021 | #define PCI_DEVICE_ID_ARECA_1680 0x1680 | ||
2022 | #define PCI_DEVICE_ID_ARECA_1681 0x1681 | ||
2023 | |||
2007 | #define PCI_VENDOR_ID_S2IO 0x17d5 | 2024 | #define PCI_VENDOR_ID_S2IO 0x17d5 |
2008 | #define PCI_DEVICE_ID_S2IO_WIN 0x5731 | 2025 | #define PCI_DEVICE_ID_S2IO_WIN 0x5731 |
2009 | #define PCI_DEVICE_ID_S2IO_UNI 0x5831 | 2026 | #define PCI_DEVICE_ID_S2IO_UNI 0x5831 |
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index c60b8ff2f5e..1bc67520141 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h | |||
@@ -25,13 +25,6 @@ extern const unsigned char scsi_command_size[8]; | |||
25 | #define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7] | 25 | #define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7] |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * SCSI device types | ||
29 | */ | ||
30 | |||
31 | #define MAX_SCSI_DEVICE_CODE 15 | ||
32 | extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE]; | ||
33 | |||
34 | /* | ||
35 | * Special value for scanning to specify scanning or rescanning of all | 28 | * Special value for scanning to specify scanning or rescanning of all |
36 | * possible channels, (target) ids, or luns on a given shost. | 29 | * possible channels, (target) ids, or luns on a given shost. |
37 | */ | 30 | */ |
@@ -225,6 +218,9 @@ static inline int scsi_status_is_good(int status) | |||
225 | #define TYPE_RBC 0x0e | 218 | #define TYPE_RBC 0x0e |
226 | #define TYPE_NO_LUN 0x7f | 219 | #define TYPE_NO_LUN 0x7f |
227 | 220 | ||
221 | /* Returns a human-readable name for the device */ | ||
222 | extern const char * scsi_device_type(unsigned type); | ||
223 | |||
228 | /* | 224 | /* |
229 | * standard mode-select header prepended to all mode-select commands | 225 | * standard mode-select header prepended to all mode-select commands |
230 | */ | 226 | */ |
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 58e6444eebe..be117f812de 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h | |||
@@ -118,20 +118,6 @@ struct scsi_cmnd { | |||
118 | unsigned long pid; /* Process ID, starts at 0. Unique per host. */ | 118 | unsigned long pid; /* Process ID, starts at 0. Unique per host. */ |
119 | }; | 119 | }; |
120 | 120 | ||
121 | /* | ||
122 | * These are the values that scsi_cmd->state can take. | ||
123 | */ | ||
124 | #define SCSI_STATE_TIMEOUT 0x1000 | ||
125 | #define SCSI_STATE_FINISHED 0x1001 | ||
126 | #define SCSI_STATE_FAILED 0x1002 | ||
127 | #define SCSI_STATE_QUEUED 0x1003 | ||
128 | #define SCSI_STATE_UNUSED 0x1006 | ||
129 | #define SCSI_STATE_DISCONNECTING 0x1008 | ||
130 | #define SCSI_STATE_INITIALIZING 0x1009 | ||
131 | #define SCSI_STATE_BHQUEUE 0x100a | ||
132 | #define SCSI_STATE_MLQUEUE 0x100b | ||
133 | |||
134 | |||
135 | extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t); | 121 | extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t); |
136 | extern void scsi_put_command(struct scsi_cmnd *); | 122 | extern void scsi_put_command(struct scsi_cmnd *); |
137 | extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); | 123 | extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); |
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 6d28b031765..c74be5dabfe 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h | |||
@@ -312,7 +312,6 @@ struct fc_host_attrs { | |||
312 | u64 permanent_port_name; | 312 | u64 permanent_port_name; |
313 | u32 supported_classes; | 313 | u32 supported_classes; |
314 | u8 supported_fc4s[FC_FC4_LIST_SIZE]; | 314 | u8 supported_fc4s[FC_FC4_LIST_SIZE]; |
315 | char symbolic_name[FC_SYMBOLIC_NAME_SIZE]; | ||
316 | u32 supported_speeds; | 315 | u32 supported_speeds; |
317 | u32 maxframe_size; | 316 | u32 maxframe_size; |
318 | char serial_number[FC_SERIAL_NUMBER_SIZE]; | 317 | char serial_number[FC_SERIAL_NUMBER_SIZE]; |
@@ -324,6 +323,8 @@ struct fc_host_attrs { | |||
324 | u8 active_fc4s[FC_FC4_LIST_SIZE]; | 323 | u8 active_fc4s[FC_FC4_LIST_SIZE]; |
325 | u32 speed; | 324 | u32 speed; |
326 | u64 fabric_name; | 325 | u64 fabric_name; |
326 | char symbolic_name[FC_SYMBOLIC_NAME_SIZE]; | ||
327 | char system_hostname[FC_SYMBOLIC_NAME_SIZE]; | ||
327 | 328 | ||
328 | /* Private (Transport-managed) Attributes */ | 329 | /* Private (Transport-managed) Attributes */ |
329 | enum fc_tgtid_binding_type tgtid_bind_type; | 330 | enum fc_tgtid_binding_type tgtid_bind_type; |
@@ -354,8 +355,6 @@ struct fc_host_attrs { | |||
354 | (((struct fc_host_attrs *)(x)->shost_data)->supported_classes) | 355 | (((struct fc_host_attrs *)(x)->shost_data)->supported_classes) |
355 | #define fc_host_supported_fc4s(x) \ | 356 | #define fc_host_supported_fc4s(x) \ |
356 | (((struct fc_host_attrs *)(x)->shost_data)->supported_fc4s) | 357 | (((struct fc_host_attrs *)(x)->shost_data)->supported_fc4s) |
357 | #define fc_host_symbolic_name(x) \ | ||
358 | (((struct fc_host_attrs *)(x)->shost_data)->symbolic_name) | ||
359 | #define fc_host_supported_speeds(x) \ | 358 | #define fc_host_supported_speeds(x) \ |
360 | (((struct fc_host_attrs *)(x)->shost_data)->supported_speeds) | 359 | (((struct fc_host_attrs *)(x)->shost_data)->supported_speeds) |
361 | #define fc_host_maxframe_size(x) \ | 360 | #define fc_host_maxframe_size(x) \ |
@@ -374,6 +373,10 @@ struct fc_host_attrs { | |||
374 | (((struct fc_host_attrs *)(x)->shost_data)->speed) | 373 | (((struct fc_host_attrs *)(x)->shost_data)->speed) |
375 | #define fc_host_fabric_name(x) \ | 374 | #define fc_host_fabric_name(x) \ |
376 | (((struct fc_host_attrs *)(x)->shost_data)->fabric_name) | 375 | (((struct fc_host_attrs *)(x)->shost_data)->fabric_name) |
376 | #define fc_host_symbolic_name(x) \ | ||
377 | (((struct fc_host_attrs *)(x)->shost_data)->symbolic_name) | ||
378 | #define fc_host_system_hostname(x) \ | ||
379 | (((struct fc_host_attrs *)(x)->shost_data)->system_hostname) | ||
377 | #define fc_host_tgtid_bind_type(x) \ | 380 | #define fc_host_tgtid_bind_type(x) \ |
378 | (((struct fc_host_attrs *)(x)->shost_data)->tgtid_bind_type) | 381 | (((struct fc_host_attrs *)(x)->shost_data)->tgtid_bind_type) |
379 | #define fc_host_rports(x) \ | 382 | #define fc_host_rports(x) \ |
@@ -409,6 +412,8 @@ struct fc_function_template { | |||
409 | void (*get_host_active_fc4s)(struct Scsi_Host *); | 412 | void (*get_host_active_fc4s)(struct Scsi_Host *); |
410 | void (*get_host_speed)(struct Scsi_Host *); | 413 | void (*get_host_speed)(struct Scsi_Host *); |
411 | void (*get_host_fabric_name)(struct Scsi_Host *); | 414 | void (*get_host_fabric_name)(struct Scsi_Host *); |
415 | void (*get_host_symbolic_name)(struct Scsi_Host *); | ||
416 | void (*set_host_system_hostname)(struct Scsi_Host *); | ||
412 | 417 | ||
413 | struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *); | 418 | struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *); |
414 | void (*reset_fc_host_stats)(struct Scsi_Host *); | 419 | void (*reset_fc_host_stats)(struct Scsi_Host *); |
@@ -445,7 +450,6 @@ struct fc_function_template { | |||
445 | unsigned long show_host_permanent_port_name:1; | 450 | unsigned long show_host_permanent_port_name:1; |
446 | unsigned long show_host_supported_classes:1; | 451 | unsigned long show_host_supported_classes:1; |
447 | unsigned long show_host_supported_fc4s:1; | 452 | unsigned long show_host_supported_fc4s:1; |
448 | unsigned long show_host_symbolic_name:1; | ||
449 | unsigned long show_host_supported_speeds:1; | 453 | unsigned long show_host_supported_speeds:1; |
450 | unsigned long show_host_maxframe_size:1; | 454 | unsigned long show_host_maxframe_size:1; |
451 | unsigned long show_host_serial_number:1; | 455 | unsigned long show_host_serial_number:1; |
@@ -456,6 +460,8 @@ struct fc_function_template { | |||
456 | unsigned long show_host_active_fc4s:1; | 460 | unsigned long show_host_active_fc4s:1; |
457 | unsigned long show_host_speed:1; | 461 | unsigned long show_host_speed:1; |
458 | unsigned long show_host_fabric_name:1; | 462 | unsigned long show_host_fabric_name:1; |
463 | unsigned long show_host_symbolic_name:1; | ||
464 | unsigned long show_host_system_hostname:1; | ||
459 | }; | 465 | }; |
460 | 466 | ||
461 | 467 | ||
@@ -491,6 +497,25 @@ fc_remote_port_chkready(struct fc_rport *rport) | |||
491 | return result; | 497 | return result; |
492 | } | 498 | } |
493 | 499 | ||
500 | static inline u64 wwn_to_u64(u8 *wwn) | ||
501 | { | ||
502 | return (u64)wwn[0] << 56 | (u64)wwn[1] << 48 | | ||
503 | (u64)wwn[2] << 40 | (u64)wwn[3] << 32 | | ||
504 | (u64)wwn[4] << 24 | (u64)wwn[5] << 16 | | ||
505 | (u64)wwn[6] << 8 | (u64)wwn[7]; | ||
506 | } | ||
507 | |||
508 | static inline void u64_to_wwn(u64 inm, u8 *wwn) | ||
509 | { | ||
510 | wwn[0] = (inm >> 56) & 0xff; | ||
511 | wwn[1] = (inm >> 48) & 0xff; | ||
512 | wwn[2] = (inm >> 40) & 0xff; | ||
513 | wwn[3] = (inm >> 32) & 0xff; | ||
514 | wwn[4] = (inm >> 24) & 0xff; | ||
515 | wwn[5] = (inm >> 16) & 0xff; | ||
516 | wwn[6] = (inm >> 8) & 0xff; | ||
517 | wwn[7] = inm & 0xff; | ||
518 | } | ||
494 | 519 | ||
495 | struct scsi_transport_template *fc_attach_transport( | 520 | struct scsi_transport_template *fc_attach_transport( |
496 | struct fc_function_template *); | 521 | struct fc_function_template *); |
@@ -502,12 +527,4 @@ void fc_remote_port_delete(struct fc_rport *rport); | |||
502 | void fc_remote_port_rolechg(struct fc_rport *rport, u32 roles); | 527 | void fc_remote_port_rolechg(struct fc_rport *rport, u32 roles); |
503 | int scsi_is_fc_rport(const struct device *); | 528 | int scsi_is_fc_rport(const struct device *); |
504 | 529 | ||
505 | static inline u64 wwn_to_u64(u8 *wwn) | ||
506 | { | ||
507 | return (u64)wwn[0] << 56 | (u64)wwn[1] << 48 | | ||
508 | (u64)wwn[2] << 40 | (u64)wwn[3] << 32 | | ||
509 | (u64)wwn[4] << 24 | (u64)wwn[5] << 16 | | ||
510 | (u64)wwn[6] << 8 | (u64)wwn[7]; | ||
511 | } | ||
512 | |||
513 | #endif /* SCSI_TRANSPORT_FC_H */ | 530 | #endif /* SCSI_TRANSPORT_FC_H */ |