Lines 1-641
Link Here
|
1 |
--- os_freebsd.c.orig Sun Oct 9 13:00:56 2005 |
|
|
2 |
+++ os_freebsd.c Sun Oct 9 13:00:46 2005 |
3 |
@@ -18,6 +18,7 @@ |
4 |
#include <stdio.h> |
5 |
#include <sys/types.h> |
6 |
#include <dirent.h> |
7 |
+#include <fcntl.h> |
8 |
#include <err.h> |
9 |
#include <camlib.h> |
10 |
#include <cam/scsi/scsi_message.h> |
11 |
@@ -109,7 +110,11 @@ |
12 |
} |
13 |
|
14 |
if (parse_ok == CONTROLLER_ATA) { |
15 |
+#ifdef IOCATAREQUEST |
16 |
+ if ((fdchan->device = open(dev,O_RDONLY))<0) { |
17 |
+#else |
18 |
if ((fdchan->atacommand = open("/dev/ata",O_RDWR))<0) { |
19 |
+#endif |
20 |
int myerror = errno; //preserve across free call |
21 |
free (fdchan); |
22 |
errno = myerror; |
23 |
@@ -120,7 +125,26 @@ |
24 |
if (parse_ok == CONTROLLER_3WARE_678K_CHAR) { |
25 |
char buf[512]; |
26 |
sprintf(buf,"/dev/twe%d",fdchan->device); |
27 |
+#ifdef IOCATAREQUEST |
28 |
+ if ((fdchan->device = open(buf,O_RDWR))<0) { |
29 |
+#else |
30 |
if ((fdchan->atacommand = open(buf,O_RDWR))<0) { |
31 |
+#endif |
32 |
+ int myerror = errno; // preserver across free call |
33 |
+ free(fdchan); |
34 |
+ errno=myerror; |
35 |
+ return -1; |
36 |
+ } |
37 |
+ } |
38 |
+ |
39 |
+ if (parse_ok == CONTROLLER_3WARE_9000_CHAR) { |
40 |
+ char buf[512]; |
41 |
+ sprintf(buf,"/dev/twa%d",fdchan->device); |
42 |
+#ifdef IOCATAREQUEST |
43 |
+ if ((fdchan->device = open(buf,O_RDWR))<0) { |
44 |
+#else |
45 |
+ if ((fdchan->atacommand = open(buf,O_RDWR))<0) { |
46 |
+#endif |
47 |
int myerror = errno; // preserver across free call |
48 |
free(fdchan); |
49 |
errno=myerror; |
50 |
@@ -167,8 +191,13 @@ |
51 |
free(fdchan->devname); |
52 |
|
53 |
// close device, if open |
54 |
+#ifdef IOCATAREQUEST |
55 |
+ if (fdchan->device) |
56 |
+ failed=close(fdchan->device); |
57 |
+#else |
58 |
if (fdchan->atacommand) |
59 |
failed=close(fdchan->atacommand); |
60 |
+#endif |
61 |
|
62 |
if (fdchan->scsicontrol) |
63 |
failed=close(fdchan->scsicontrol); |
64 |
@@ -221,7 +250,7 @@ |
65 |
} |
66 |
|
67 |
int ata_command_interface(int fd, smart_command_set command, int select, char *data) { |
68 |
-#ifndef ATAREQUEST |
69 |
+#if !defined(ATAREQUEST) && !defined(IOCATAREQUEST) |
70 |
// sorry, but without ATAng, we can't do anything here |
71 |
printwarning(BAD_KERNEL,NULL); |
72 |
errno = ENOSYS; |
73 |
@@ -229,7 +258,11 @@ |
74 |
#else |
75 |
struct freebsd_dev_channel* con; |
76 |
int retval, copydata=0; |
77 |
+#ifdef IOCATAREQUEST |
78 |
+ struct ata_ioc_request request; |
79 |
+#else |
80 |
struct ata_cmd iocmd; |
81 |
+#endif |
82 |
unsigned char buff[512]; |
83 |
|
84 |
// check that "file descriptor" is valid |
85 |
@@ -238,89 +271,97 @@ |
86 |
|
87 |
bzero(buff,512); |
88 |
|
89 |
+#ifdef IOCATAREQUEST |
90 |
+ bzero(&request,sizeof(struct ata_ioc_request)); |
91 |
+#else |
92 |
bzero(&iocmd,sizeof(struct ata_cmd)); |
93 |
+#endif |
94 |
bzero(buff,512); |
95 |
+ |
96 |
+#ifndef IOCATAREQUEST |
97 |
iocmd.cmd=ATAREQUEST; |
98 |
iocmd.channel=con->channel; |
99 |
iocmd.device=con->device; |
100 |
+#define request iocmd.u.request |
101 |
+#endif |
102 |
|
103 |
- iocmd.u.request.u.ata.command=ATA_SMART_CMD; |
104 |
- iocmd.u.request.timeout=600; |
105 |
+ request.u.ata.command=ATA_SMART_CMD; |
106 |
+ request.timeout=600; |
107 |
switch (command){ |
108 |
case READ_VALUES: |
109 |
- iocmd.u.request.u.ata.feature=ATA_SMART_READ_VALUES; |
110 |
- iocmd.u.request.u.ata.lba=0xc24f<<8; |
111 |
- iocmd.u.request.flags=ATA_CMD_READ; |
112 |
- iocmd.u.request.data=buff; |
113 |
- iocmd.u.request.count=512; |
114 |
+ request.u.ata.feature=ATA_SMART_READ_VALUES; |
115 |
+ request.u.ata.lba=0xc24f<<8; |
116 |
+ request.flags=ATA_CMD_READ; |
117 |
+ request.data=buff; |
118 |
+ request.count=512; |
119 |
copydata=1; |
120 |
break; |
121 |
case READ_THRESHOLDS: |
122 |
- iocmd.u.request.u.ata.feature=ATA_SMART_READ_THRESHOLDS; |
123 |
- iocmd.u.request.u.ata.count=1; |
124 |
- iocmd.u.request.u.ata.lba=1|(0xc24f<<8); |
125 |
- iocmd.u.request.flags=ATA_CMD_READ; |
126 |
- iocmd.u.request.data=buff; |
127 |
- iocmd.u.request.count=512; |
128 |
+ request.u.ata.feature=ATA_SMART_READ_THRESHOLDS; |
129 |
+ request.u.ata.count=1; |
130 |
+ request.u.ata.lba=1|(0xc24f<<8); |
131 |
+ request.flags=ATA_CMD_READ; |
132 |
+ request.data=buff; |
133 |
+ request.count=512; |
134 |
copydata=1; |
135 |
break; |
136 |
case READ_LOG: |
137 |
- iocmd.u.request.u.ata.feature=ATA_SMART_READ_LOG_SECTOR; |
138 |
- iocmd.u.request.u.ata.lba=select|(0xc24f<<8); |
139 |
- iocmd.u.request.u.ata.count=1; |
140 |
- iocmd.u.request.flags=ATA_CMD_READ; |
141 |
- iocmd.u.request.data=buff; |
142 |
- iocmd.u.request.count=512; |
143 |
+ request.u.ata.feature=ATA_SMART_READ_LOG_SECTOR; |
144 |
+ request.u.ata.lba=select|(0xc24f<<8); |
145 |
+ request.u.ata.count=1; |
146 |
+ request.flags=ATA_CMD_READ; |
147 |
+ request.data=buff; |
148 |
+ request.count=512; |
149 |
copydata=1; |
150 |
break; |
151 |
case IDENTIFY: |
152 |
- iocmd.u.request.u.ata.command=ATA_IDENTIFY_DEVICE; |
153 |
- iocmd.u.request.flags=ATA_CMD_READ; |
154 |
- iocmd.u.request.data=buff; |
155 |
- iocmd.u.request.count=512; |
156 |
+ request.u.ata.command=ATA_IDENTIFY_DEVICE; |
157 |
+ request.flags=ATA_CMD_READ; |
158 |
+ request.data=buff; |
159 |
+ request.count=512; |
160 |
copydata=1; |
161 |
break; |
162 |
case PIDENTIFY: |
163 |
- iocmd.u.request.u.ata.command=ATA_IDENTIFY_PACKET_DEVICE; |
164 |
- iocmd.u.request.flags=ATA_CMD_READ; |
165 |
- iocmd.u.request.data=buff; |
166 |
- iocmd.u.request.count=512; |
167 |
+ request.u.ata.command=ATA_IDENTIFY_PACKET_DEVICE; |
168 |
+ request.flags=ATA_CMD_READ; |
169 |
+ request.data=buff; |
170 |
+ request.count=512; |
171 |
copydata=1; |
172 |
break; |
173 |
case ENABLE: |
174 |
- iocmd.u.request.u.ata.feature=ATA_SMART_ENABLE; |
175 |
- iocmd.u.request.u.ata.lba=0xc24f<<8; |
176 |
- iocmd.u.request.flags=ATA_CMD_CONTROL; |
177 |
+ request.u.ata.feature=ATA_SMART_ENABLE; |
178 |
+ request.u.ata.lba=0xc24f<<8; |
179 |
+ request.flags=ATA_CMD_CONTROL; |
180 |
break; |
181 |
case DISABLE: |
182 |
- iocmd.u.request.u.ata.feature=ATA_SMART_DISABLE; |
183 |
- iocmd.u.request.u.ata.lba=0xc24f<<8; |
184 |
- iocmd.u.request.flags=ATA_CMD_CONTROL; |
185 |
+ request.u.ata.feature=ATA_SMART_DISABLE; |
186 |
+ request.u.ata.lba=0xc24f<<8; |
187 |
+ request.flags=ATA_CMD_CONTROL; |
188 |
break; |
189 |
case AUTO_OFFLINE: |
190 |
// NOTE: According to ATAPI 4 and UP, this command is obsolete |
191 |
- iocmd.u.request.u.ata.feature=ATA_SMART_AUTO_OFFLINE; |
192 |
- iocmd.u.request.u.ata.lba=select|(0xc24f<<8); |
193 |
- iocmd.u.request.flags=ATA_CMD_CONTROL; |
194 |
+ request.u.ata.feature=ATA_SMART_AUTO_OFFLINE; |
195 |
+ request.u.ata.lba=select|(0xc24f<<8); |
196 |
+ request.flags=ATA_CMD_CONTROL; |
197 |
break; |
198 |
case AUTOSAVE: |
199 |
- iocmd.u.request.u.ata.feature=ATA_SMART_AUTOSAVE; |
200 |
- iocmd.u.request.u.ata.count=0xf1; // to enable autosave |
201 |
- iocmd.u.request.u.ata.lba=0xc24f<<8; |
202 |
- iocmd.u.request.flags=ATA_CMD_CONTROL; |
203 |
+ request.u.ata.feature=ATA_SMART_AUTOSAVE; |
204 |
+ request.u.ata.count=0xf1; // to enable autosave |
205 |
+ request.u.ata.lba=0xc24f<<8; |
206 |
+ request.flags=ATA_CMD_CONTROL; |
207 |
break; |
208 |
case IMMEDIATE_OFFLINE: |
209 |
- iocmd.u.request.u.ata.feature=ATA_SMART_IMMEDIATE_OFFLINE; |
210 |
- iocmd.u.request.u.ata.lba = select|(0xc24f<<8); // put test in sector |
211 |
- iocmd.u.request.flags=ATA_CMD_CONTROL; |
212 |
+ request.u.ata.feature=ATA_SMART_IMMEDIATE_OFFLINE; |
213 |
+ request.u.ata.lba = select|(0xc24f<<8); // put test in sector |
214 |
+ request.flags=ATA_CMD_CONTROL; |
215 |
break; |
216 |
case STATUS_CHECK: // same command, no HDIO in FreeBSD |
217 |
case STATUS: |
218 |
// this command only says if SMART is working. It could be |
219 |
// replaced with STATUS_CHECK below. |
220 |
- iocmd.u.request.u.ata.feature=ATA_SMART_STATUS; |
221 |
- iocmd.u.request.u.ata.lba=0xc24f<<8; |
222 |
- iocmd.u.request.flags=ATA_CMD_CONTROL; |
223 |
+ request.u.ata.feature=ATA_SMART_STATUS; |
224 |
+ request.u.ata.lba=0xc24f<<8; |
225 |
+ request.flags=ATA_CMD_CONTROL; |
226 |
break; |
227 |
default: |
228 |
pout("Unrecognized command %d in ata_command_interface()\n" |
229 |
@@ -334,15 +375,19 @@ |
230 |
unsigned const char failed_lo=0xf4, failed_hi=0x2c; |
231 |
unsigned char low,high; |
232 |
|
233 |
- if ((retval=ioctl(con->atacommand, IOCATA, &iocmd))) |
234 |
+#ifdef IOCATAREQUEST |
235 |
+ if ((retval=ioctl(con->device, IOCATAREQUEST, &request)) || request.error) |
236 |
+#else |
237 |
+ if ((retval=ioctl(con->atacommand, IOCATA, &iocmd)) || request.error) |
238 |
+#endif |
239 |
return -1; |
240 |
|
241 |
#if __FreeBSD_version < 502000 |
242 |
printwarning(NO_RETURN,NULL); |
243 |
#endif |
244 |
|
245 |
- high = (iocmd.u.request.u.ata.lba >> 16) & 0xff; |
246 |
- low = (iocmd.u.request.u.ata.lba >> 8) & 0xff; |
247 |
+ high = (request.u.ata.lba >> 16) & 0xff; |
248 |
+ low = (request.u.ata.lba >> 8) & 0xff; |
249 |
|
250 |
// Cyl low and Cyl high unchanged means "Good SMART status" |
251 |
if (low==normal_lo && high==normal_hi) |
252 |
@@ -355,21 +400,23 @@ |
253 |
// We haven't gotten output that makes sense; print out some debugging info |
254 |
char buf[512]; |
255 |
sprintf(buf,"CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n", |
256 |
- (int)iocmd.u.request.u.ata.command, |
257 |
- (int)iocmd.u.request.u.ata.feature, |
258 |
- (int)iocmd.u.request.u.ata.count, |
259 |
- (int)((iocmd.u.request.u.ata.lba) & 0xff), |
260 |
- (int)((iocmd.u.request.u.ata.lba>>8) & 0xff), |
261 |
- (int)((iocmd.u.request.u.ata.lba>>16) & 0xff), |
262 |
- (int)iocmd.u.request.error); |
263 |
+ (int)request.u.ata.command, |
264 |
+ (int)request.u.ata.feature, |
265 |
+ (int)request.u.ata.count, |
266 |
+ (int)((request.u.ata.lba) & 0xff), |
267 |
+ (int)((request.u.ata.lba>>8) & 0xff), |
268 |
+ (int)((request.u.ata.lba>>16) & 0xff), |
269 |
+ (int)request.error); |
270 |
printwarning(BAD_SMART,buf); |
271 |
return 0; |
272 |
} |
273 |
|
274 |
- if ((retval=ioctl(con->atacommand, IOCATA, &iocmd))) { |
275 |
- perror("Failed command: "); |
276 |
+#ifdef IOCATAREQUEST |
277 |
+ if ((retval=ioctl(con->device, IOCATAREQUEST, &request)) || request.error) |
278 |
+#else |
279 |
+ if ((retval=ioctl(con->atacommand, IOCATA, &iocmd)) || request.error) |
280 |
+#endif |
281 |
return -1; |
282 |
- } |
283 |
// |
284 |
if (copydata) |
285 |
memcpy(data, buff, 512); |
286 |
@@ -483,16 +530,22 @@ |
287 |
|
288 |
// Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c |
289 |
|
290 |
+#define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520 |
291 |
+#define BUFFER_LEN_9000_CHAR ( sizeof(TW_OSLI_IOCTL_NO_DATA_BUF) + sizeof(TWE_Command) ) // 2048 |
292 |
+#define TW_IOCTL_BUFFER_SIZE ( MAX(BUFFER_LEN_678K_CHAR, BUFFER_LEN_9000_CHAR) ) |
293 |
+ |
294 |
int escalade_command_interface(int fd, int disknum, int escalade_type, smart_command_set command, int select, char *data) { |
295 |
// to hold true file descriptor |
296 |
struct freebsd_dev_channel* con; |
297 |
|
298 |
// return value and buffer for ioctl() |
299 |
int ioctlreturn, readdata=0; |
300 |
- struct twe_usercommand* cmd = NULL; |
301 |
+ struct twe_usercommand* cmd_twe = NULL; |
302 |
+ TW_OSLI_IOCTL_NO_DATA_BUF* cmd_twa = NULL; |
303 |
+ TWE_Command_ATA* ata = NULL; |
304 |
|
305 |
// Used by both the SCSI and char interfaces |
306 |
- char ioctl_buffer[sizeof(struct twe_usercommand)]; |
307 |
+ char ioctl_buffer[TW_IOCTL_BUFFER_SIZE]; |
308 |
|
309 |
if (disknum < 0) { |
310 |
printwarning(NO_DISK_3WARE,NULL); |
311 |
@@ -503,27 +556,40 @@ |
312 |
if (isnotopen(&fd,&con)) |
313 |
return -1; |
314 |
|
315 |
- memset(ioctl_buffer, 0, sizeof(struct twe_usercommand)); |
316 |
+ memset(ioctl_buffer, 0, TW_IOCTL_BUFFER_SIZE); |
317 |
|
318 |
- cmd = (struct twe_usercommand*)ioctl_buffer; |
319 |
- cmd->tu_command.ata.opcode = TWE_OP_ATA_PASSTHROUGH; |
320 |
+ if (escalade_type==CONTROLLER_3WARE_9000_CHAR) { |
321 |
+ cmd_twa = (TW_OSLI_IOCTL_NO_DATA_BUF*)ioctl_buffer; |
322 |
+ cmd_twa->pdata = ((TW_OSLI_IOCTL_WITH_PAYLOAD*)cmd_twa)->payload.data_buf; |
323 |
+ cmd_twa->driver_pkt.buffer_length = 512; |
324 |
+ ata = (TWE_Command_ATA*)&cmd_twa->cmd_pkt.command.cmd_pkt_7k; |
325 |
+ } else if (escalade_type==CONTROLLER_3WARE_678K_CHAR) { |
326 |
+ cmd_twe = (struct twe_usercommand*)ioctl_buffer; |
327 |
+ ata = &cmd_twe->tu_command.ata; |
328 |
+ } else { |
329 |
+ pout("Unrecognized escalade_type %d in freebsd_3ware_command_interface(disk %d)\n" |
330 |
+ "Please contact " PACKAGE_BUGREPORT "\n", escalade_type, disknum); |
331 |
+ errno=ENOSYS; |
332 |
+ return -1; |
333 |
+ } |
334 |
|
335 |
// Same for (almost) all commands - but some reset below |
336 |
- cmd->tu_command.ata.request_id = 0xFF; |
337 |
- cmd->tu_command.ata.unit = disknum; |
338 |
- cmd->tu_command.ata.host_id = 0; |
339 |
- cmd->tu_command.ata.status = 0; |
340 |
- cmd->tu_command.ata.flags = 0x1; |
341 |
- cmd->tu_command.ata.drive_head = 0x0; |
342 |
- cmd->tu_command.ata.sector_num = 0; |
343 |
+ ata->opcode = TWE_OP_ATA_PASSTHROUGH; |
344 |
+ ata->request_id = 0xFF; |
345 |
+ ata->unit = disknum; |
346 |
+ ata->host_id = 0; |
347 |
+ ata->status = 0; |
348 |
+ ata->flags = 0x1; |
349 |
+ ata->drive_head = 0x0; |
350 |
+ ata->sector_num = 0; |
351 |
|
352 |
// All SMART commands use this CL/CH signature. These are magic |
353 |
// values from the ATA specifications. |
354 |
- cmd->tu_command.ata.cylinder_lo = 0x4F; |
355 |
- cmd->tu_command.ata.cylinder_hi = 0xC2; |
356 |
+ ata->cylinder_lo = 0x4F; |
357 |
+ ata->cylinder_hi = 0xC2; |
358 |
|
359 |
// SMART ATA COMMAND REGISTER value |
360 |
- cmd->tu_command.ata.command = ATA_SMART_CMD; |
361 |
+ ata->command = ATA_SMART_CMD; |
362 |
|
363 |
// Is this a command that reads or returns 512 bytes? |
364 |
// passthru->param values are: |
365 |
@@ -538,61 +604,63 @@ |
366 |
command == IDENTIFY || |
367 |
command == WRITE_LOG ) { |
368 |
readdata=1; |
369 |
- cmd->tu_size = 512; |
370 |
- cmd->tu_data = data; |
371 |
- cmd->tu_command.ata.sgl_offset = 0x5; |
372 |
- cmd->tu_command.ata.size = 0x5; |
373 |
- cmd->tu_command.ata.param = 0xD; |
374 |
- cmd->tu_command.ata.sector_count = 0x1; |
375 |
+ if (escalade_type==CONTROLLER_3WARE_678K_CHAR) { |
376 |
+ cmd_twe->tu_data = data; |
377 |
+ cmd_twe->tu_size = 512; |
378 |
+ } |
379 |
+ ata->sgl_offset = 0x5; |
380 |
+ ata->size = 0x5; |
381 |
+ ata->param = 0xD; |
382 |
+ ata->sector_count = 0x1; |
383 |
// For 64-bit to work correctly, up the size of the command packet |
384 |
// in dwords by 1 to account for the 64-bit single sgl 'address' |
385 |
// field. Note that this doesn't agree with the typedefs but it's |
386 |
// right (agree with kernel driver behavior/typedefs). |
387 |
- //if (sizeof(long)==8) |
388 |
- // cmd->tu_command.ata.size++; |
389 |
+ //if (escalade_type==CONTROLLER_3WARE_9000_CHAR && sizeof(long)==8) |
390 |
+ // ata->size++; |
391 |
} |
392 |
else { |
393 |
// Non data command -- but doesn't use large sector |
394 |
// count register values. |
395 |
- cmd->tu_command.ata.sgl_offset = 0x0; |
396 |
- cmd->tu_command.ata.size = 0x5; |
397 |
- cmd->tu_command.ata.param = 0x8; |
398 |
- cmd->tu_command.ata.sector_count = 0x0; |
399 |
+ ata->sgl_offset = 0x0; |
400 |
+ ata->size = 0x5; |
401 |
+ ata->param = 0x8; |
402 |
+ ata->sector_count = 0x0; |
403 |
} |
404 |
|
405 |
// Now set ATA registers depending upon command |
406 |
switch (command){ |
407 |
case CHECK_POWER_MODE: |
408 |
- cmd->tu_command.ata.command = ATA_CHECK_POWER_MODE; |
409 |
- cmd->tu_command.ata.features = 0; |
410 |
- cmd->tu_command.ata.cylinder_lo = 0; |
411 |
- cmd->tu_command.ata.cylinder_hi = 0; |
412 |
+ ata->command = ATA_CHECK_POWER_MODE; |
413 |
+ ata->features = 0; |
414 |
+ ata->cylinder_lo = 0; |
415 |
+ ata->cylinder_hi = 0; |
416 |
break; |
417 |
case READ_VALUES: |
418 |
- cmd->tu_command.ata.features = ATA_SMART_READ_VALUES; |
419 |
+ ata->features = ATA_SMART_READ_VALUES; |
420 |
break; |
421 |
case READ_THRESHOLDS: |
422 |
- cmd->tu_command.ata.features = ATA_SMART_READ_THRESHOLDS; |
423 |
+ ata->features = ATA_SMART_READ_THRESHOLDS; |
424 |
break; |
425 |
case READ_LOG: |
426 |
- cmd->tu_command.ata.features = ATA_SMART_READ_LOG_SECTOR; |
427 |
+ ata->features = ATA_SMART_READ_LOG_SECTOR; |
428 |
// log number to return |
429 |
- cmd->tu_command.ata.sector_num = select; |
430 |
+ ata->sector_num = select; |
431 |
break; |
432 |
case WRITE_LOG: |
433 |
- cmd->tu_data = data; |
434 |
+ if (escalade_type==CONTROLLER_3WARE_9000_CHAR) |
435 |
+ memcpy(cmd_twa->pdata, data, 512); |
436 |
readdata=0; |
437 |
- cmd->tu_command.ata.features = ATA_SMART_WRITE_LOG_SECTOR; |
438 |
- cmd->tu_command.ata.sector_count = 1; |
439 |
- cmd->tu_command.ata.sector_num = select; |
440 |
- cmd->tu_command.ata.param = 0xF; // PIO data write |
441 |
+ ata->features = ATA_SMART_WRITE_LOG_SECTOR; |
442 |
+ ata->sector_num = select; |
443 |
+ ata->param = 0xF; // PIO data write |
444 |
break; |
445 |
case IDENTIFY: |
446 |
// ATA IDENTIFY DEVICE |
447 |
- cmd->tu_command.ata.command = ATA_IDENTIFY_DEVICE; |
448 |
- cmd->tu_command.ata.features = 0; |
449 |
- cmd->tu_command.ata.cylinder_lo = 0; |
450 |
- cmd->tu_command.ata.cylinder_hi = 0; |
451 |
+ ata->command = ATA_IDENTIFY_DEVICE; |
452 |
+ ata->features = 0; |
453 |
+ ata->cylinder_lo = 0; |
454 |
+ ata->cylinder_hi = 0; |
455 |
break; |
456 |
case PIDENTIFY: |
457 |
// 3WARE controller can NOT have packet device internally |
458 |
@@ -600,34 +668,34 @@ |
459 |
errno=ENODEV; |
460 |
return -1; |
461 |
case ENABLE: |
462 |
- cmd->tu_command.ata.features = ATA_SMART_ENABLE; |
463 |
+ ata->features = ATA_SMART_ENABLE; |
464 |
break; |
465 |
case DISABLE: |
466 |
- cmd->tu_command.ata.features = ATA_SMART_DISABLE; |
467 |
+ ata->features = ATA_SMART_DISABLE; |
468 |
break; |
469 |
case AUTO_OFFLINE: |
470 |
- cmd->tu_command.ata.features = ATA_SMART_AUTO_OFFLINE; |
471 |
+ ata->features = ATA_SMART_AUTO_OFFLINE; |
472 |
// Enable or disable? |
473 |
- cmd->tu_command.ata.sector_count = select; |
474 |
+ ata->sector_count = select; |
475 |
break; |
476 |
case AUTOSAVE: |
477 |
- cmd->tu_command.ata.features = ATA_SMART_AUTOSAVE; |
478 |
+ ata->features = ATA_SMART_AUTOSAVE; |
479 |
// Enable or disable? |
480 |
- cmd->tu_command.ata.sector_count = select; |
481 |
+ ata->sector_count = select; |
482 |
break; |
483 |
case IMMEDIATE_OFFLINE: |
484 |
- cmd->tu_command.ata.features = ATA_SMART_IMMEDIATE_OFFLINE; |
485 |
+ ata->features = ATA_SMART_IMMEDIATE_OFFLINE; |
486 |
// What test type to run? |
487 |
- cmd->tu_command.ata.sector_num = select; |
488 |
+ ata->sector_num = select; |
489 |
break; |
490 |
case STATUS_CHECK: |
491 |
- cmd->tu_command.ata.features = ATA_SMART_STATUS; |
492 |
+ ata->features = ATA_SMART_STATUS; |
493 |
break; |
494 |
case STATUS: |
495 |
// This is JUST to see if SMART is enabled, by giving SMART status |
496 |
// command. But it doesn't say if status was good, or failing. |
497 |
// See below for the difference. |
498 |
- cmd->tu_command.ata.features = ATA_SMART_STATUS; |
499 |
+ ata->features = ATA_SMART_STATUS; |
500 |
break; |
501 |
default: |
502 |
pout("Unrecognized command %d in freebsd_3ware_command_interface(disk %d)\n" |
503 |
@@ -637,7 +705,19 @@ |
504 |
} |
505 |
|
506 |
// Now send the command down through an ioctl() |
507 |
- ioctlreturn=ioctl(con->atacommand,TWEIO_COMMAND,cmd); |
508 |
+ if (escalade_type==CONTROLLER_3WARE_9000_CHAR) { |
509 |
+#ifdef IOCATAREQUEST |
510 |
+ ioctlreturn=ioctl(con->device,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa); |
511 |
+#else |
512 |
+ ioctlreturn=ioctl(con->atacommand,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa); |
513 |
+#endif |
514 |
+ } else { |
515 |
+#ifdef IOCATAREQUEST |
516 |
+ ioctlreturn=ioctl(con->device,TWEIO_COMMAND,cmd_twe); |
517 |
+#else |
518 |
+ ioctlreturn=ioctl(con->atacommand,TWEIO_COMMAND,cmd_twe); |
519 |
+#endif |
520 |
+ } |
521 |
|
522 |
// Deal with the different error cases |
523 |
if (ioctlreturn) { |
524 |
@@ -648,9 +728,9 @@ |
525 |
|
526 |
// See if the ATA command failed. Now that we have returned from |
527 |
// the ioctl() call, if passthru is valid, then: |
528 |
- // - cmd->tu_command.ata.status contains the 3ware controller STATUS |
529 |
- // - cmd->tu_command.ata.command contains the ATA STATUS register |
530 |
- // - cmd->tu_command.ata.features contains the ATA ERROR register |
531 |
+ // - ata->status contains the 3ware controller STATUS |
532 |
+ // - ata->command contains the ATA STATUS register |
533 |
+ // - ata->features contains the ATA ERROR register |
534 |
// |
535 |
// Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS |
536 |
// If bit 0 (error bit) is set, then ATA ERROR register is valid. |
537 |
@@ -658,21 +738,27 @@ |
538 |
// doesn't make much sense: we don't care in detail why the error |
539 |
// happened. |
540 |
|
541 |
- if (cmd->tu_command.ata.status || (cmd->tu_command.ata.command & 0x21)) { |
542 |
- pout("Command failed, ata.status=(0x%2.2x), ata.command=(0x%2.2x), ata.flags=(0x%2.2x)\n",cmd->tu_command.ata.status,cmd->tu_command.ata.command,cmd->tu_command.ata.flags); |
543 |
+ if (ata->status || (ata->command & 0x21)) { |
544 |
+ pout("Command failed, ata.status=(0x%2.2x), ata.command=(0x%2.2x), ata.flags=(0x%2.2x)\n",ata->status,ata->command,ata->flags); |
545 |
errno=EIO; |
546 |
return -1; |
547 |
} |
548 |
|
549 |
+ // If this is a read data command, copy data to output buffer |
550 |
+ if (readdata) { |
551 |
+ if (escalade_type==CONTROLLER_3WARE_9000_CHAR) |
552 |
+ memcpy(data, cmd_twa->pdata, 512); |
553 |
+ } |
554 |
+ |
555 |
// For STATUS_CHECK, we need to check register values |
556 |
if (command==STATUS_CHECK) { |
557 |
|
558 |
// To find out if the SMART RETURN STATUS is good or failing, we |
559 |
// need to examine the values of the Cylinder Low and Cylinder |
560 |
// High Registers. |
561 |
- |
562 |
- unsigned short cyl_lo=cmd->tu_command.ata.cylinder_lo; |
563 |
- unsigned short cyl_hi=cmd->tu_command.ata.cylinder_hi; |
564 |
+ |
565 |
+ unsigned short cyl_lo=ata->cylinder_lo; |
566 |
+ unsigned short cyl_hi=ata->cylinder_hi; |
567 |
|
568 |
// If values in Cyl-LO and Cyl-HI are unchanged, SMART status is good. |
569 |
if (cyl_lo==0x4F && cyl_hi==0xC2) |
570 |
@@ -688,7 +774,7 @@ |
571 |
|
572 |
// copy sector count register (one byte!) to return data |
573 |
if (command==CHECK_POWER_MODE) |
574 |
- *data=*(char *)&(cmd->tu_command.ata.sector_count); |
575 |
+ *data=*(char *)&(ata->sector_count); |
576 |
|
577 |
// look for nonexistent devices/ports |
578 |
if (command==IDENTIFY && !nonempty((unsigned char *)data, 512)) { |
579 |
@@ -709,6 +795,14 @@ |
580 |
return 0; |
581 |
} |
582 |
|
583 |
+static int get_twa_channel_unit (const char* name, int* unit, int* dev) { |
584 |
+ if (sscanf(name, "twa%d", dev) != 1) |
585 |
+ return -1; |
586 |
+ *unit=0; // not really needed for TWA drives, as we handle that seperately |
587 |
+ return 0; |
588 |
+} |
589 |
+ |
590 |
+#ifndef IOCATAREQUEST |
591 |
static int get_ata_channel_unit ( const char* name, int* unit, int* dev) { |
592 |
#ifndef ATAREQUEST |
593 |
*dev=0; |
594 |
@@ -756,7 +850,7 @@ |
595 |
return 0; |
596 |
#endif |
597 |
} |
598 |
- |
599 |
+#endif |
600 |
|
601 |
// Guess device type (ata or scsi) based on device name (FreeBSD |
602 |
// specific) SCSI device name in FreeBSD can be sd, sr, scd, st, nst, |
603 |
@@ -768,6 +862,7 @@ |
604 |
static const char * fbsd_dev_scsi_tape2 = "nsa"; |
605 |
static const char * fbsd_dev_scsi_tape3 = "esa"; |
606 |
static const char * fbsd_dev_twe_disk = "twed"; |
607 |
+static const char * fbsd_dev_twa_disk = "twa"; |
608 |
|
609 |
static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel *chan) { |
610 |
int len; |
611 |
@@ -788,11 +883,13 @@ |
612 |
// form /dev/ad* or ad* |
613 |
if (!strncmp(fbsd_dev_ata_disk_prefix, dev_name, |
614 |
strlen(fbsd_dev_ata_disk_prefix))) { |
615 |
+#ifndef IOCATAREQUEST |
616 |
if (chan != NULL) { |
617 |
if (get_ata_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) { |
618 |
return CONTROLLER_UNKNOWN; |
619 |
} |
620 |
} |
621 |
+#endif |
622 |
return CONTROLLER_ATA; |
623 |
} |
624 |
|
625 |
@@ -824,6 +921,16 @@ |
626 |
} |
627 |
} |
628 |
return CONTROLLER_3WARE_678K_CHAR; |
629 |
+ } |
630 |
+ |
631 |
+ if (!strncmp(fbsd_dev_twa_disk,dev_name, |
632 |
+ strlen(fbsd_dev_twa_disk))) { |
633 |
+ if (chan != NULL) { |
634 |
+ if (get_twa_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) { |
635 |
+ return CONTROLLER_UNKNOWN; |
636 |
+ } |
637 |
+ } |
638 |
+ return CONTROLLER_3WARE_9000_CHAR; |
639 |
} |
640 |
|
641 |
// we failed to recognize any of the forms |