]> git.proxmox.com Git - mirror_smartmontools-debian.git/blob - os_freebsd.c
add debian specific patches
[mirror_smartmontools-debian.git] / os_freebsd.c
1 /*
2 * os_freebsd.c
3 *
4 * Home page of code is: http://smartmontools.sourceforge.net
5 *
6 * Copyright (C) 2003-6 Eduard Martinescu <smartmontools-support@lists.sourceforge.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * You should have received a copy of the GNU General Public License
14 * (for example COPYING); if not, write to the Free
15 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 */
17
18 #include <stdio.h>
19 #include <sys/types.h>
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <err.h>
23 #include <camlib.h>
24 #include <cam/scsi/scsi_message.h>
25 #include <sys/ata.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <glob.h>
30 #include <fcntl.h>
31 #include <stddef.h>
32
33
34 #include "config.h"
35 #include "int64.h"
36 #include "atacmds.h"
37 #include "scsicmds.h"
38 #include "utility.h"
39 #include "os_freebsd.h"
40
41 static const char *filenameandversion="$Id: os_freebsd.c,v 1.49 2006/04/12 14:54:28 ballen4705 Exp $";
42
43 const char *os_XXXX_c_cvsid="$Id: os_freebsd.c,v 1.49 2006/04/12 14:54:28 ballen4705 Exp $" \
44 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
45
46 // to hold onto exit code for atexit routine
47 extern int exitstatus;
48
49 // Private table of open devices: guaranteed zero on startup since
50 // part of static data.
51 struct freebsd_dev_channel *devicetable[FREEBSD_MAXDEV];
52
53 // forward declaration
54 static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel *ch);
55
56 // print examples for smartctl
57 void print_smartctl_examples(){
58 printf("=================================================== SMARTCTL EXAMPLES =====\n\n");
59 #ifdef HAVE_GETOPT_LONG
60 printf(
61 " smartctl -a /dev/ad0 (Prints all SMART information)\n\n"
62 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/ad0\n"
63 " (Enables SMART on first disk)\n\n"
64 " smartctl -t long /dev/ad0 (Executes extended disk self-test)\n\n"
65 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/ad0\n"
66 " (Prints Self-Test & Attribute errors)\n"
67 " (Prints Self-Test & Attribute errors)\n\n"
68 " smartctl -a --device=3ware,2 /dev/twa0\n"
69 " smartctl -a --device=3ware,2 /dev/twe0\n"
70 " (Prints all SMART information for ATA disk on\n"
71 " third port of first 3ware RAID controller)\n"
72 );
73 #else
74 printf(
75 " smartctl -a /dev/ad0 (Prints all SMART information)\n"
76 " smartctl -s on -o on -S on /dev/ad0 (Enables SMART on first disk)\n"
77 " smartctl -t long /dev/ad0 (Executes extended disk self-test)\n"
78 " smartctl -A -l selftest -q errorsonly /dev/ad0\n"
79 " (Prints Self-Test & Attribute errors)\n"
80 " smartctl -a -d 3ware,2 /dev/twa0\n"
81 " smartctl -a -d 3ware,2 /dev/twe0\n"
82 );
83 #endif
84 return;
85 }
86
87 // Like open(). Return positive integer handle, used by functions below only. mode=="ATA" or "SCSI".
88 int deviceopen (const char* dev, char* mode __unused) {
89 struct freebsd_dev_channel *fdchan;
90 int parse_ok, i;
91
92 // Search table for a free entry
93 for (i=0; i<FREEBSD_MAXDEV; i++)
94 if (!devicetable[i])
95 break;
96
97 // If no free entry found, return error. We have max allowed number
98 // of "file descriptors" already allocated.
99 if (i==FREEBSD_MAXDEV) {
100 errno=EMFILE;
101 return -1;
102 }
103
104 fdchan = calloc(1,sizeof(struct freebsd_dev_channel));
105 if (fdchan == NULL) {
106 // errno already set by call to malloc()
107 return -1;
108 }
109
110 parse_ok = parse_ata_chan_dev (dev,fdchan);
111 if (parse_ok == CONTROLLER_UNKNOWN) {
112 free(fdchan);
113 errno = ENOTTY;
114 return -1; // can't handle what we don't know
115 }
116
117 if (parse_ok == CONTROLLER_ATA) {
118 #ifdef IOCATAREQUEST
119 if ((fdchan->device = open(dev,O_RDONLY))<0) {
120 #else
121 if ((fdchan->atacommand = open("/dev/ata",O_RDWR))<0) {
122 #endif
123 int myerror = errno; //preserve across free call
124 free (fdchan);
125 errno = myerror;
126 return -1;
127 }
128 }
129
130 if (parse_ok == CONTROLLER_3WARE_678K_CHAR) {
131 char buf[512];
132 sprintf(buf,"/dev/twe%d",fdchan->device);
133 #ifdef IOCATAREQUEST
134 if ((fdchan->device = open(buf,O_RDWR))<0) {
135 #else
136 if ((fdchan->atacommand = open(buf,O_RDWR))<0) {
137 #endif
138 int myerror = errno; // preserver across free call
139 free(fdchan);
140 errno=myerror;
141 return -1;
142 }
143 }
144
145 if (parse_ok == CONTROLLER_3WARE_9000_CHAR) {
146 char buf[512];
147 sprintf(buf,"/dev/twa%d",fdchan->device);
148 #ifdef IOCATAREQUEST
149 if ((fdchan->device = open(buf,O_RDWR))<0) {
150 #else
151 if ((fdchan->atacommand = open(buf,O_RDWR))<0) {
152 #endif
153 int myerror = errno; // preserver across free call
154 free(fdchan);
155 errno=myerror;
156 return -1;
157 }
158 }
159
160 if (parse_ok == CONTROLLER_SCSI) {
161 // this is really a NO-OP, as the parse takes care
162 // of filling in correct details
163 }
164
165 // return pointer to "file descriptor" table entry, properly offset.
166 devicetable[i]=fdchan;
167 return i+FREEBSD_FDOFFSET;
168 }
169
170 // Returns 1 if device not available/open/found else 0. Also shifts fd into valid range.
171 static int isnotopen(int *fd, struct freebsd_dev_channel** fdchan) {
172 // put valid "file descriptor" into range 0...FREEBSD_MAXDEV-1
173 *fd -= FREEBSD_FDOFFSET;
174
175 // check for validity of "file descriptor".
176 if (*fd<0 || *fd>=FREEBSD_MAXDEV || !((*fdchan)=devicetable[*fd])) {
177 errno = ENODEV;
178 return 1;
179 }
180
181 return 0;
182 }
183
184 // Like close(). Acts on handles returned by above function.
185 int deviceclose (int fd) {
186 struct freebsd_dev_channel *fdchan;
187 int failed = 0;
188
189 // check for valid file descriptor
190 if (isnotopen(&fd, &fdchan))
191 return -1;
192
193
194 // did we allocate a SCSI device name?
195 if (fdchan->devname)
196 free(fdchan->devname);
197
198 // close device, if open
199 #ifdef IOCATAREQUEST
200 if (fdchan->device)
201 failed=close(fdchan->device);
202 #else
203 if (fdchan->atacommand)
204 failed=close(fdchan->atacommand);
205 #endif
206
207 if (fdchan->scsicontrol)
208 failed=close(fdchan->scsicontrol);
209
210 // if close succeeded, then remove from device list
211 // Eduard, should we also remove it from list if close() fails? I'm
212 // not sure. Here I only remove it from list if close() worked.
213 if (!failed) {
214 free(fdchan);
215 devicetable[fd]=NULL;
216 }
217
218 return failed;
219 }
220
221 #define NO_RETURN 0
222 #define BAD_SMART 1
223 #define NO_DISK_3WARE 2
224 #define BAD_KERNEL 3
225 #define MAX_MSG 3
226
227 // Utility function for printing warnings
228 void printwarning(int msgNo, const char* extra) {
229 static int printed[] = {0,0,0,0};
230 static const char* message[]={
231 "The SMART RETURN STATUS return value (smartmontools -H option/Directive)\n can not be retrieved with this version of ATAng, please do not rely on this value\nYou should update to at least 5.2\n",
232
233 "Error SMART Status command failed\nPlease get assistance from \n" PACKAGE_HOMEPAGE "\nRegister values returned from SMART Status command are:\n",
234
235 "You must specify a DISK # for 3ware drives with -d 3ware,<n> where <n> begins with 1 for first disk drive\n",
236
237 "ATA support is not provided for this kernel version. Please ugrade to a recent 5-CURRENT kernel (post 09/01/2003 or so)\n"
238 };
239
240 if (msgNo >= 0 && msgNo <= MAX_MSG) {
241 if (!printed[msgNo]) {
242 printed[msgNo] = 1;
243 pout("%s", message[msgNo]);
244 if (extra)
245 pout("%s",extra);
246 }
247 }
248 return;
249 }
250
251
252 // Interface to ATA devices. See os_linux.c
253 int marvell_command_interface(int fd __unused, smart_command_set command __unused, int select __unused, char *data __unused) {
254 return -1;
255 }
256
257 int ata_command_interface(int fd, smart_command_set command, int select, char *data) {
258 #if !defined(ATAREQUEST) && !defined(IOCATAREQUEST)
259 // sorry, but without ATAng, we can't do anything here
260 printwarning(BAD_KERNEL,NULL);
261 errno = ENOSYS;
262 return -1;
263 #else
264 struct freebsd_dev_channel* con;
265 int retval, copydata=0;
266 #ifdef IOCATAREQUEST
267 struct ata_ioc_request request;
268 #else
269 struct ata_cmd iocmd;
270 #endif
271 unsigned char buff[512];
272
273 // check that "file descriptor" is valid
274 if (isnotopen(&fd,&con))
275 return -1;
276
277 bzero(buff,512);
278
279 #ifdef IOCATAREQUEST
280 bzero(&request,sizeof(struct ata_ioc_request));
281 #else
282 bzero(&iocmd,sizeof(struct ata_cmd));
283 #endif
284 bzero(buff,512);
285
286 #ifndef IOCATAREQUEST
287 iocmd.cmd=ATAREQUEST;
288 iocmd.channel=con->channel;
289 iocmd.device=con->device;
290 #define request iocmd.u.request
291 #endif
292
293 request.u.ata.command=ATA_SMART_CMD;
294 request.timeout=600;
295 switch (command){
296 case READ_VALUES:
297 request.u.ata.feature=ATA_SMART_READ_VALUES;
298 request.u.ata.lba=0xc24f<<8;
299 request.flags=ATA_CMD_READ;
300 request.data=buff;
301 request.count=512;
302 copydata=1;
303 break;
304 case READ_THRESHOLDS:
305 request.u.ata.feature=ATA_SMART_READ_THRESHOLDS;
306 request.u.ata.count=1;
307 request.u.ata.lba=1|(0xc24f<<8);
308 request.flags=ATA_CMD_READ;
309 request.data=buff;
310 request.count=512;
311 copydata=1;
312 break;
313 case READ_LOG:
314 request.u.ata.feature=ATA_SMART_READ_LOG_SECTOR;
315 request.u.ata.lba=select|(0xc24f<<8);
316 request.u.ata.count=1;
317 request.flags=ATA_CMD_READ;
318 request.data=buff;
319 request.count=512;
320 copydata=1;
321 break;
322 case IDENTIFY:
323 request.u.ata.command=ATA_IDENTIFY_DEVICE;
324 request.flags=ATA_CMD_READ;
325 request.data=buff;
326 request.count=512;
327 copydata=1;
328 break;
329 case PIDENTIFY:
330 request.u.ata.command=ATA_IDENTIFY_PACKET_DEVICE;
331 request.flags=ATA_CMD_READ;
332 request.data=buff;
333 request.count=512;
334 copydata=1;
335 break;
336 case ENABLE:
337 request.u.ata.feature=ATA_SMART_ENABLE;
338 request.u.ata.lba=0xc24f<<8;
339 request.flags=ATA_CMD_CONTROL;
340 break;
341 case DISABLE:
342 request.u.ata.feature=ATA_SMART_DISABLE;
343 request.u.ata.lba=0xc24f<<8;
344 request.flags=ATA_CMD_CONTROL;
345 break;
346 case AUTO_OFFLINE:
347 // NOTE: According to ATAPI 4 and UP, this command is obsolete
348 request.u.ata.feature=ATA_SMART_AUTO_OFFLINE;
349 request.u.ata.lba=select|(0xc24f<<8);
350 request.flags=ATA_CMD_CONTROL;
351 break;
352 case AUTOSAVE:
353 request.u.ata.feature=ATA_SMART_AUTOSAVE;
354 request.u.ata.count=0xf1; // to enable autosave
355 request.u.ata.lba=0xc24f<<8;
356 request.flags=ATA_CMD_CONTROL;
357 break;
358 case IMMEDIATE_OFFLINE:
359 request.u.ata.feature=ATA_SMART_IMMEDIATE_OFFLINE;
360 request.u.ata.lba = select|(0xc24f<<8); // put test in sector
361 request.flags=ATA_CMD_CONTROL;
362 break;
363 case STATUS_CHECK: // same command, no HDIO in FreeBSD
364 case STATUS:
365 // this command only says if SMART is working. It could be
366 // replaced with STATUS_CHECK below.
367 request.u.ata.feature=ATA_SMART_STATUS;
368 request.u.ata.lba=0xc24f<<8;
369 request.flags=ATA_CMD_CONTROL;
370 break;
371 default:
372 pout("Unrecognized command %d in ata_command_interface()\n"
373 "Please contact " PACKAGE_BUGREPORT "\n", command);
374 errno=ENOSYS;
375 return -1;
376 }
377
378 if (command==STATUS_CHECK){
379 unsigned const char normal_lo=0x4f, normal_hi=0xc2;
380 unsigned const char failed_lo=0xf4, failed_hi=0x2c;
381 unsigned char low,high;
382
383 #ifdef IOCATAREQUEST
384 if ((retval=ioctl(con->device, IOCATAREQUEST, &request)) || request.error)
385 #else
386 if ((retval=ioctl(con->atacommand, IOCATA, &iocmd)) || request.error)
387 #endif
388 return -1;
389
390 #if __FreeBSD_version < 502000
391 printwarning(NO_RETURN,NULL);
392 #endif
393
394 high = (request.u.ata.lba >> 16) & 0xff;
395 low = (request.u.ata.lba >> 8) & 0xff;
396
397 // Cyl low and Cyl high unchanged means "Good SMART status"
398 if (low==normal_lo && high==normal_hi)
399 return 0;
400
401 // These values mean "Bad SMART status"
402 if (low==failed_lo && high==failed_hi)
403 return 1;
404
405 // We haven't gotten output that makes sense; print out some debugging info
406 char buf[512];
407 sprintf(buf,"CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
408 (int)request.u.ata.command,
409 (int)request.u.ata.feature,
410 (int)request.u.ata.count,
411 (int)((request.u.ata.lba) & 0xff),
412 (int)((request.u.ata.lba>>8) & 0xff),
413 (int)((request.u.ata.lba>>16) & 0xff),
414 (int)request.error);
415 printwarning(BAD_SMART,buf);
416 return 0;
417 }
418
419 #ifdef IOCATAREQUEST
420 if ((retval=ioctl(con->device, IOCATAREQUEST, &request)) || request.error)
421 #else
422 if ((retval=ioctl(con->atacommand, IOCATA, &iocmd)) || request.error)
423 #endif
424 {
425 return -1;
426 }
427 //
428 if (copydata)
429 memcpy(data, buff, 512);
430
431 return 0;
432 #endif
433 }
434
435
436 // Interface to SCSI devices. See os_linux.c
437 int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
438 {
439 struct freebsd_dev_channel* con = NULL;
440 struct cam_device* cam_dev = NULL;
441 union ccb *ccb;
442
443
444 if (report > 0) {
445 unsigned int k;
446 const unsigned char * ucp = iop->cmnd;
447 const char * np;
448
449 np = scsi_get_opcode_name(ucp[0]);
450 pout(" [%s: ", np ? np : "<unknown opcode>");
451 for (k = 0; k < iop->cmnd_len; ++k)
452 pout("%02x ", ucp[k]);
453 if ((report > 1) &&
454 (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
455 int trunc = (iop->dxfer_len > 256) ? 1 : 0;
456
457 pout("]\n Outgoing data, len=%d%s:\n", (int)iop->dxfer_len,
458 (trunc ? " [only first 256 bytes shown]" : ""));
459 dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
460 }
461 else
462 pout("]");
463 }
464
465 // check that "file descriptor" is valid
466 if (isnotopen(&fd,&con))
467 return -ENOTTY;
468
469
470 if (!(cam_dev = cam_open_spec_device(con->devname,con->unitnum,O_RDWR,NULL))) {
471 warnx("%s",cam_errbuf);
472 return -1;
473 }
474
475 if (!(ccb = cam_getccb(cam_dev))) {
476 warnx("error allocating ccb");
477 return -ENOMEM;
478 }
479
480 // clear out structure, except for header that was filled in for us
481 bzero(&(&ccb->ccb_h)[1],
482 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
483
484 cam_fill_csio(&ccb->csio,
485 /*retrires*/ 1,
486 /*cbfcnp*/ NULL,
487 /* flags */ (iop->dxfer_dir == DXFER_NONE ? CAM_DIR_NONE :(iop->dxfer_dir == DXFER_FROM_DEVICE ? CAM_DIR_IN : CAM_DIR_OUT)),
488 /* tagaction */ MSG_SIMPLE_Q_TAG,
489 /* dataptr */ iop->dxferp,
490 /* datalen */ iop->dxfer_len,
491 /* senselen */ iop->max_sense_len,
492 /* cdblen */ iop->cmnd_len,
493 /* timout (converted to seconds) */ iop->timeout*1000);
494 memcpy(ccb->csio.cdb_io.cdb_bytes,iop->cmnd,iop->cmnd_len);
495
496 if (cam_send_ccb(cam_dev,ccb) < 0) {
497 warn("error sending SCSI ccb");
498 #if __FreeBSD_version > 500000
499 cam_error_print(cam_dev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
500 #endif
501 cam_freeccb(ccb);
502 return -1;
503 }
504
505 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
506 #if __FreeBSD_version > 500000
507 cam_error_print(cam_dev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
508 #endif
509 cam_freeccb(ccb);
510 return -1;
511 }
512
513 if (iop->sensep) {
514 memcpy(iop->sensep,&(ccb->csio.sense_data),sizeof(struct scsi_sense_data));
515 iop->resp_sense_len = sizeof(struct scsi_sense_data);
516 }
517
518 iop->scsi_status = ccb->csio.scsi_status;
519
520 cam_freeccb(ccb);
521
522 if (cam_dev)
523 cam_close_device(cam_dev);
524
525 if (report > 0) {
526 int trunc;
527
528 pout(" status=0\n");
529 trunc = (iop->dxfer_len > 256) ? 1 : 0;
530
531 pout(" Incoming data, len=%d%s:\n", (int)iop->dxfer_len,
532 (trunc ? " [only first 256 bytes shown]" : ""));
533 dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
534 }
535 return 0;
536 }
537
538 // Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c
539
540 #define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520
541 #define BUFFER_LEN_9000_CHAR ( sizeof(TW_OSLI_IOCTL_NO_DATA_BUF) + sizeof(TWE_Command) ) // 2048
542 #define TW_IOCTL_BUFFER_SIZE ( MAX(BUFFER_LEN_678K_CHAR, BUFFER_LEN_9000_CHAR) )
543
544 int escalade_command_interface(int fd, int disknum, int escalade_type, smart_command_set command, int select, char *data) {
545 // to hold true file descriptor
546 struct freebsd_dev_channel* con;
547
548 // return value and buffer for ioctl()
549 int ioctlreturn, readdata=0;
550 struct twe_usercommand* cmd_twe = NULL;
551 TW_OSLI_IOCTL_NO_DATA_BUF* cmd_twa = NULL;
552 TWE_Command_ATA* ata = NULL;
553
554 // Used by both the SCSI and char interfaces
555 char ioctl_buffer[TW_IOCTL_BUFFER_SIZE];
556
557 if (disknum < 0) {
558 printwarning(NO_DISK_3WARE,NULL);
559 return -1;
560 }
561
562 // check that "file descriptor" is valid
563 if (isnotopen(&fd,&con))
564 return -1;
565
566 memset(ioctl_buffer, 0, TW_IOCTL_BUFFER_SIZE);
567
568 if (escalade_type==CONTROLLER_3WARE_9000_CHAR) {
569 cmd_twa = (TW_OSLI_IOCTL_NO_DATA_BUF*)ioctl_buffer;
570 cmd_twa->pdata = ((TW_OSLI_IOCTL_WITH_PAYLOAD*)cmd_twa)->payload.data_buf;
571 cmd_twa->driver_pkt.buffer_length = 512;
572 ata = (TWE_Command_ATA*)&cmd_twa->cmd_pkt.command.cmd_pkt_7k;
573 } else if (escalade_type==CONTROLLER_3WARE_678K_CHAR) {
574 cmd_twe = (struct twe_usercommand*)ioctl_buffer;
575 ata = &cmd_twe->tu_command.ata;
576 } else {
577 pout("Unrecognized escalade_type %d in freebsd_3ware_command_interface(disk %d)\n"
578 "Please contact " PACKAGE_BUGREPORT "\n", escalade_type, disknum);
579 errno=ENOSYS;
580 return -1;
581 }
582
583 ata->opcode = TWE_OP_ATA_PASSTHROUGH;
584
585 // Same for (almost) all commands - but some reset below
586 ata->request_id = 0xFF;
587 ata->unit = disknum;
588 ata->host_id = 0;
589 ata->status = 0;
590 ata->flags = 0x1;
591 ata->drive_head = 0x0;
592 ata->sector_num = 0;
593
594 // All SMART commands use this CL/CH signature. These are magic
595 // values from the ATA specifications.
596 ata->cylinder_lo = 0x4F;
597 ata->cylinder_hi = 0xC2;
598
599 // SMART ATA COMMAND REGISTER value
600 ata->command = ATA_SMART_CMD;
601
602 // Is this a command that reads or returns 512 bytes?
603 // passthru->param values are:
604 // 0x0 - non data command without TFR write check,
605 // 0x8 - non data command with TFR write check,
606 // 0xD - data command that returns data to host from device
607 // 0xF - data command that writes data from host to device
608 // passthru->size values are 0x5 for non-data and 0x07 for data
609 if (command == READ_VALUES ||
610 command == READ_THRESHOLDS ||
611 command == READ_LOG ||
612 command == IDENTIFY ||
613 command == WRITE_LOG ) {
614 readdata=1;
615 if (escalade_type==CONTROLLER_3WARE_678K_CHAR) {
616 cmd_twe->tu_data = data;
617 cmd_twe->tu_size = 512;
618 }
619 ata->sgl_offset = 0x5;
620 ata->size = 0x5;
621 ata->param = 0xD;
622 ata->sector_count = 0x1;
623 // For 64-bit to work correctly, up the size of the command packet
624 // in dwords by 1 to account for the 64-bit single sgl 'address'
625 // field. Note that this doesn't agree with the typedefs but it's
626 // right (agree with kernel driver behavior/typedefs).
627 //if (sizeof(long)==8)
628 // ata->size++;
629 }
630 else {
631 // Non data command -- but doesn't use large sector
632 // count register values.
633 ata->sgl_offset = 0x0;
634 ata->size = 0x5;
635 ata->param = 0x8;
636 ata->sector_count = 0x0;
637 }
638
639 // Now set ATA registers depending upon command
640 switch (command){
641 case CHECK_POWER_MODE:
642 ata->command = ATA_CHECK_POWER_MODE;
643 ata->features = 0;
644 ata->cylinder_lo = 0;
645 ata->cylinder_hi = 0;
646 break;
647 case READ_VALUES:
648 ata->features = ATA_SMART_READ_VALUES;
649 break;
650 case READ_THRESHOLDS:
651 ata->features = ATA_SMART_READ_THRESHOLDS;
652 break;
653 case READ_LOG:
654 ata->features = ATA_SMART_READ_LOG_SECTOR;
655 // log number to return
656 ata->sector_num = select;
657 break;
658 case WRITE_LOG:
659 readdata=0;
660 ata->features = ATA_SMART_WRITE_LOG_SECTOR;
661 ata->sector_count = 1;
662 ata->sector_num = select;
663 ata->param = 0xF; // PIO data write
664 break;
665 case IDENTIFY:
666 // ATA IDENTIFY DEVICE
667 ata->command = ATA_IDENTIFY_DEVICE;
668 ata->features = 0;
669 ata->cylinder_lo = 0;
670 ata->cylinder_hi = 0;
671 break;
672 case PIDENTIFY:
673 // 3WARE controller can NOT have packet device internally
674 pout("WARNING - NO DEVICE FOUND ON 3WARE CONTROLLER (disk %d)\n", disknum);
675 errno=ENODEV;
676 return -1;
677 case ENABLE:
678 ata->features = ATA_SMART_ENABLE;
679 break;
680 case DISABLE:
681 ata->features = ATA_SMART_DISABLE;
682 break;
683 case AUTO_OFFLINE:
684 ata->features = ATA_SMART_AUTO_OFFLINE;
685 // Enable or disable?
686 ata->sector_count = select;
687 break;
688 case AUTOSAVE:
689 ata->features = ATA_SMART_AUTOSAVE;
690 // Enable or disable?
691 ata->sector_count = select;
692 break;
693 case IMMEDIATE_OFFLINE:
694 ata->features = ATA_SMART_IMMEDIATE_OFFLINE;
695 // What test type to run?
696 ata->sector_num = select;
697 break;
698 case STATUS_CHECK:
699 ata->features = ATA_SMART_STATUS;
700 break;
701 case STATUS:
702 // This is JUST to see if SMART is enabled, by giving SMART status
703 // command. But it doesn't say if status was good, or failing.
704 // See below for the difference.
705 ata->features = ATA_SMART_STATUS;
706 break;
707 default:
708 pout("Unrecognized command %d in freebsd_3ware_command_interface(disk %d)\n"
709 "Please contact " PACKAGE_BUGREPORT "\n", command, disknum);
710 errno=ENOSYS;
711 return -1;
712 }
713
714 // Now send the command down through an ioctl()
715 if (escalade_type==CONTROLLER_3WARE_9000_CHAR) {
716 #ifdef IOCATAREQUEST
717 ioctlreturn=ioctl(con->device,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa);
718 #else
719 ioctlreturn=ioctl(con->atacommand,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa);
720 #endif
721 } else {
722 #ifdef IOCATAREQUEST
723 ioctlreturn=ioctl(con->device,TWEIO_COMMAND,cmd_twe);
724 #else
725 ioctlreturn=ioctl(con->atacommand,TWEIO_COMMAND,cmd_twe);
726 #endif
727 }
728
729 // Deal with the different error cases
730 if (ioctlreturn) {
731 if (!errno)
732 errno=EIO;
733 return -1;
734 }
735
736 // See if the ATA command failed. Now that we have returned from
737 // the ioctl() call, if passthru is valid, then:
738 // - ata->status contains the 3ware controller STATUS
739 // - ata->command contains the ATA STATUS register
740 // - ata->features contains the ATA ERROR register
741 //
742 // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS
743 // If bit 0 (error bit) is set, then ATA ERROR register is valid.
744 // While we *might* decode the ATA ERROR register, at the moment it
745 // doesn't make much sense: we don't care in detail why the error
746 // happened.
747
748 if (ata->status || (ata->command & 0x21)) {
749 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);
750 errno=EIO;
751 return -1;
752 }
753
754 // If this is a read data command, copy data to output buffer
755 if (readdata) {
756 if (escalade_type==CONTROLLER_3WARE_9000_CHAR)
757 memcpy(data, cmd_twa->pdata, 512);
758 }
759
760 // For STATUS_CHECK, we need to check register values
761 if (command==STATUS_CHECK) {
762
763 // To find out if the SMART RETURN STATUS is good or failing, we
764 // need to examine the values of the Cylinder Low and Cylinder
765 // High Registers.
766
767 unsigned short cyl_lo=ata->cylinder_lo;
768 unsigned short cyl_hi=ata->cylinder_hi;
769
770 // If values in Cyl-LO and Cyl-HI are unchanged, SMART status is good.
771 if (cyl_lo==0x4F && cyl_hi==0xC2)
772 return 0;
773
774 // If values in Cyl-LO and Cyl-HI are as follows, SMART status is FAIL
775 if (cyl_lo==0xF4 && cyl_hi==0x2C)
776 return 1;
777
778 errno=EIO;
779 return -1;
780 }
781
782 // copy sector count register (one byte!) to return data
783 if (command==CHECK_POWER_MODE)
784 *data=*(char *)&(ata->sector_count);
785
786 // look for nonexistent devices/ports
787 if (command==IDENTIFY && !nonempty((unsigned char *)data, 512)) {
788 errno=ENODEV;
789 return -1;
790 }
791
792 return 0;
793 }
794
795 static int get_tw_channel_unit (const char* name, int* unit, int* dev) {
796 const char *p;
797
798 /* device node sanity check */
799 for (p = name + 3; *p; p++)
800 if (*p < '0' || *p > '9')
801 return -1;
802 if (strlen(name) > 4 && *(name + 3) == '0')
803 return -1;
804
805 if (dev != NULL)
806 *dev=atoi(name + 3);
807
808 /* no need for unit number */
809 if (unit != NULL)
810 *unit=0;
811 return 0;
812 }
813
814
815 #ifndef IOCATAREQUEST
816 static int get_ata_channel_unit ( const char* name, int* unit, int* dev) {
817 #ifndef ATAREQUEST
818 *dev=0;
819 *unit=0;
820 return 0;
821 #else
822 // there is no direct correlation between name 'ad0, ad1, ...' and
823 // channel/unit number. So we need to iterate through the possible
824 // channels and check each unit to see if we match names
825 struct ata_cmd iocmd;
826 int fd,maxunit;
827
828 bzero(&iocmd, sizeof(struct ata_cmd));
829
830 if ((fd = open("/dev/ata", O_RDWR)) < 0)
831 return -errno;
832
833 iocmd.cmd = ATAGMAXCHANNEL;
834 if (ioctl(fd, IOCATA, &iocmd) < 0) {
835 return -errno;
836 close(fd);
837 }
838 maxunit = iocmd.u.maxchan;
839 for (*unit = 0; *unit < maxunit; (*unit)++) {
840 iocmd.channel = *unit;
841 iocmd.device = -1;
842 iocmd.cmd = ATAGPARM;
843 if (ioctl(fd, IOCATA, &iocmd) < 0) {
844 close(fd);
845 return -errno;
846 }
847 if (iocmd.u.param.type[0] && !strcmp(name,iocmd.u.param.name[0])) {
848 *dev = 0;
849 break;
850 }
851 if (iocmd.u.param.type[1] && !strcmp(name,iocmd.u.param.name[1])) {
852 *dev = 1;
853 break;
854 }
855 }
856 close(fd);
857 if (*unit == maxunit)
858 return -1;
859 else
860 return 0;
861 #endif
862 }
863 #endif
864
865 // Guess device type (ata or scsi) based on device name (FreeBSD
866 // specific) SCSI device name in FreeBSD can be sd, sr, scd, st, nst,
867 // osst, nosst and sg.
868 static const char * fbsd_dev_prefix = "/dev/";
869 static const char * fbsd_dev_ata_disk_prefix = "ad";
870 static const char * fbsd_dev_scsi_disk_plus = "da";
871 static const char * fbsd_dev_scsi_tape1 = "sa";
872 static const char * fbsd_dev_scsi_tape2 = "nsa";
873 static const char * fbsd_dev_scsi_tape3 = "esa";
874 static const char * fbsd_dev_twe_ctrl = "twe";
875 static const char * fbsd_dev_twa_ctrl = "twa";
876
877 static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel *chan) {
878 int len;
879 int dev_prefix_len = strlen(fbsd_dev_prefix);
880
881 // if dev_name null, or string length zero
882 if (!dev_name || !(len = strlen(dev_name)))
883 return CONTROLLER_UNKNOWN;
884
885 // Remove the leading /dev/... if it's there
886 if (!strncmp(fbsd_dev_prefix, dev_name, dev_prefix_len)) {
887 if (len <= dev_prefix_len)
888 // if nothing else in the string, unrecognized
889 return CONTROLLER_UNKNOWN;
890 // else advance pointer to following characters
891 dev_name += dev_prefix_len;
892 }
893 // form /dev/ad* or ad*
894 if (!strncmp(fbsd_dev_ata_disk_prefix, dev_name,
895 strlen(fbsd_dev_ata_disk_prefix))) {
896 #ifndef IOCATAREQUEST
897 if (chan != NULL) {
898 if (get_ata_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) {
899 return CONTROLLER_UNKNOWN;
900 }
901 }
902 #endif
903 return CONTROLLER_ATA;
904 }
905
906 // form /dev/da* or da*
907 if (!strncmp(fbsd_dev_scsi_disk_plus, dev_name,
908 strlen(fbsd_dev_scsi_disk_plus)))
909 goto handlescsi;
910
911 // form /dev/sa* or sa*
912 if (!strncmp(fbsd_dev_scsi_tape1, dev_name,
913 strlen(fbsd_dev_scsi_tape1)))
914 goto handlescsi;
915
916 // form /dev/nsa* or nsa*
917 if (!strncmp(fbsd_dev_scsi_tape2, dev_name,
918 strlen(fbsd_dev_scsi_tape2)))
919 goto handlescsi;
920
921 // form /dev/esa* or esa*
922 if (!strncmp(fbsd_dev_scsi_tape3, dev_name,
923 strlen(fbsd_dev_scsi_tape3)))
924 goto handlescsi;
925
926 if (!strncmp(fbsd_dev_twa_ctrl,dev_name,
927 strlen(fbsd_dev_twa_ctrl))) {
928 if (chan != NULL) {
929 if (get_tw_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) {
930 return CONTROLLER_UNKNOWN;
931 }
932 }
933 else if (get_tw_channel_unit(dev_name,NULL,NULL)<0) {
934 return CONTROLLER_UNKNOWN;
935 }
936 return CONTROLLER_3WARE_9000_CHAR;
937 }
938
939 if (!strncmp(fbsd_dev_twe_ctrl,dev_name,
940 strlen(fbsd_dev_twe_ctrl))) {
941 if (chan != NULL) {
942 if (get_tw_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) {
943 return CONTROLLER_UNKNOWN;
944 }
945 }
946 else if (get_tw_channel_unit(dev_name,NULL,NULL)<0) {
947 return CONTROLLER_UNKNOWN;
948 }
949 return CONTROLLER_3WARE_678K_CHAR;
950 }
951
952 // we failed to recognize any of the forms
953 return CONTROLLER_UNKNOWN;
954
955 handlescsi:
956 if (chan != NULL) {
957 if (!(chan->devname = calloc(1,DEV_IDLEN+1)))
958 return CONTROLLER_UNKNOWN;
959
960 if (cam_get_device(dev_name,chan->devname,DEV_IDLEN,&(chan->unitnum)) == -1)
961 return CONTROLLER_UNKNOWN;
962 }
963 return CONTROLLER_SCSI;
964
965 }
966
967 int guess_device_type (const char* dev_name) {
968 return parse_ata_chan_dev(dev_name,NULL);
969 }
970
971 // global variable holding byte count of allocated memory
972 extern long long bytes;
973
974 // we are going to take advantage of the fact that FreeBSD's devfs will only
975 // have device entries for devices that exist. So if we get the equivilent of
976 // ls /dev/ad?, we have all the ATA devices on the system
977 //
978 // If any errors occur, leave errno set as it was returned by the
979 // system call, and return <0.
980
981 // Return values:
982 // -1 out of memory
983 // -2 to -5 errors in glob
984
985 int get_dev_names(char*** names, const char* prefix) {
986 int n = 0;
987 char** mp;
988 int retglob,lim;
989 glob_t globbuf;
990 int i;
991 char pattern1[128],pattern2[128];
992
993 bzero(&globbuf,sizeof(globbuf));
994 // in case of non-clean exit
995 *names=NULL;
996
997 // handle 0-99 possible devices, will still be limited by MAX_NUM_DEV
998 sprintf(pattern1,"/dev/%s[0-9]",prefix);
999 sprintf(pattern2,"/dev/%s[0-9][0-9]",prefix);
1000
1001 // Use glob to look for any directory entries matching the patterns
1002 // first call inits with first pattern match, second call appends
1003 // to first list. Turn on NOCHECK for second call. This results in no
1004 // error if no more matches found, however it does append the actual
1005 // pattern to the list of paths....
1006 if ((retglob=glob(pattern1, GLOB_ERR, NULL, &globbuf)) ||
1007 (retglob=glob(pattern2, GLOB_ERR|GLOB_APPEND|GLOB_NOCHECK,NULL,&globbuf))) {
1008 int retval = -1;
1009 // glob failed
1010 if (retglob==GLOB_NOSPACE)
1011 pout("glob(3) ran out of memory matching patterns (%s),(%s)\n",
1012 pattern1, pattern2);
1013 else if (retglob==GLOB_ABORTED)
1014 pout("glob(3) aborted matching patterns (%s),(%s)\n",
1015 pattern1, pattern2);
1016 else if (retglob==GLOB_NOMATCH) {
1017 pout("glob(3) found no matches for patterns (%s),(%s)\n",
1018 pattern1, pattern2);
1019 retval = 0;
1020 }
1021 else if (retglob)
1022 pout("Unexplained error in glob(3) of patterns (%s),(%s)\n",
1023 pattern1, pattern2);
1024
1025 // Free memory and return
1026 globfree(&globbuf);
1027
1028 return retval;
1029 }
1030
1031 // did we find too many paths?
1032 // did we find too many paths?
1033 lim = globbuf.gl_pathc < MAX_NUM_DEV ? globbuf.gl_pathc : MAX_NUM_DEV;
1034 if (lim < globbuf.gl_pathc)
1035 pout("glob(3) found %d > MAX=%d devices matching patterns (%s),(%s): ignoring %d paths\n",
1036 globbuf.gl_pathc, MAX_NUM_DEV, pattern1,pattern2,
1037 globbuf.gl_pathc-MAX_NUM_DEV);
1038
1039 // allocate space for up to lim number of ATA devices
1040 if (!(mp = (char **)calloc(lim, sizeof(char*)))){
1041 pout("Out of memory constructing scan device list\n");
1042 return -1;
1043 }
1044
1045 // now step through the list returned by glob. No link checking needed
1046 // in FreeBSD
1047 for (i=0; i<globbuf.gl_pathc; i++){
1048 // becuase of the NO_CHECK on second call to glob,
1049 // the pattern itself will be added to path list..
1050 // so ignore any paths that have the ']' from pattern
1051 if (strchr(globbuf.gl_pathv[i],']') == NULL)
1052 mp[n++] = CustomStrDup(globbuf.gl_pathv[i], 1, __LINE__, filenameandversion);
1053 }
1054
1055 globfree(&globbuf);
1056 mp = realloc(mp,n*(sizeof(char*))); // shrink to correct size
1057 bytes += (n)*(sizeof(char*)); // and set allocated byte count
1058 *names=mp;
1059 return n;
1060 }
1061
1062 int make_device_names (char*** devlist, const char* name) {
1063 if (!strcmp(name,"SCSI"))
1064 return get_dev_names(devlist,"da");
1065 else if (!strcmp(name,"ATA"))
1066 return get_dev_names(devlist,"ad");
1067 else
1068 return 0;
1069 }