]> git.proxmox.com Git - mirror_smartmontools-debian.git/blame - os_freebsd.cpp
Imported Upstream version 6.1+svn3812
[mirror_smartmontools-debian.git] / os_freebsd.cpp
CommitLineData
832b75ed
GG
1/*
2 * os_freebsd.c
3 *
4 * Home page of code is: http://smartmontools.sourceforge.net
5 *
a23d5117 6 * Copyright (C) 2003-10 Eduard Martinescu <smartmontools-support@lists.sourceforge.net>
832b75ed
GG
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
ee38a438
GI
14 * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
15 *
832b75ed
GG
16 */
17
18#include <stdio.h>
19#include <sys/types.h>
20#include <dirent.h>
21#include <fcntl.h>
22#include <err.h>
cfbba5b9 23#include <errno.h>
832b75ed
GG
24#include <camlib.h>
25#include <cam/scsi/scsi_message.h>
2127e193 26#include <cam/scsi/scsi_pass.h>
1953ff6d
GG
27#if defined(__DragonFly__)
28#include <sys/nata.h>
29#else
832b75ed 30#include <sys/ata.h>
1953ff6d 31#endif
832b75ed
GG
32#include <sys/stat.h>
33#include <unistd.h>
832b75ed 34#include <glob.h>
832b75ed 35#include <stddef.h>
2127e193
GI
36#include <paths.h>
37#include <sys/utsname.h>
832b75ed
GG
38
39#include "config.h"
40#include "int64.h"
41#include "atacmds.h"
42#include "scsicmds.h"
a37e7145 43#include "cciss.h"
832b75ed
GG
44#include "utility.h"
45#include "os_freebsd.h"
46
2127e193
GI
47#include "dev_interface.h"
48#include "dev_ata_cmd_set.h"
ee38a438 49#include "dev_areca.h"
2127e193
GI
50
51#define USBDEV "/dev/usb"
54965743
GI
52#if defined(__FreeBSD_version)
53
54// This way we define one variable for the GNU/kFreeBSD and FreeBSD
55#define FREEBSDVER __FreeBSD_version
56#else
57#define FREEBSDVER __FreeBSD_kernel_version
58#endif
59
60#if (FREEBSDVER >= 800000)
61#include <libusb20_desc.h>
62#include <libusb20.h>
cfbba5b9
GI
63#elif defined(__DragonFly__)
64#include <bus/usb/usb.h>
65#include <bus/usb/usbhid.h>
54965743
GI
66#else
67#include <dev/usb/usb.h>
68#include <dev/usb/usbhid.h>
69#endif
832b75ed 70
eb07ddf2
GI
71#define CONTROLLER_3WARE_9000_CHAR 0x01
72#define CONTROLLER_3WARE_678K_CHAR 0x02
a37e7145 73
eb07ddf2
GI
74#ifndef PATHINQ_SETTINGS_SIZE
75#define PATHINQ_SETTINGS_SIZE 128
76#endif
832b75ed 77
ee38a438 78const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 3771 2013-02-10 15:36:55Z samm2 $" \
eb07ddf2 79ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
54965743 80
832b75ed
GG
81#define NO_RETURN 0
82#define BAD_SMART 1
83#define NO_DISK_3WARE 2
84#define BAD_KERNEL 3
85#define MAX_MSG 3
86
87// Utility function for printing warnings
88void printwarning(int msgNo, const char* extra) {
89 static int printed[] = {0,0,0,0};
90 static const char* message[]={
91 "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",
54965743 92
832b75ed 93 "Error SMART Status command failed\nPlease get assistance from \n" PACKAGE_HOMEPAGE "\nRegister values returned from SMART Status command are:\n",
54965743 94
832b75ed 95 "You must specify a DISK # for 3ware drives with -d 3ware,<n> where <n> begins with 1 for first disk drive\n",
54965743 96
832b75ed
GG
97 "ATA support is not provided for this kernel version. Please ugrade to a recent 5-CURRENT kernel (post 09/01/2003 or so)\n"
98 };
99
100 if (msgNo >= 0 && msgNo <= MAX_MSG) {
101 if (!printed[msgNo]) {
102 printed[msgNo] = 1;
103 pout("%s", message[msgNo]);
104 if (extra)
105 pout("%s",extra);
106 }
107 }
108 return;
109}
110
2127e193 111// Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c
832b75ed 112
2127e193
GI
113#define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520
114#define BUFFER_LEN_9000_CHAR ( sizeof(TW_OSLI_IOCTL_NO_DATA_BUF) + sizeof(TWE_Command) ) // 2048
115#define TW_IOCTL_BUFFER_SIZE ( MAX(BUFFER_LEN_678K_CHAR, BUFFER_LEN_9000_CHAR) )
4d59bff9 116
2127e193
GI
117#ifndef ATA_DEVICE
118#define ATA_DEVICE "/dev/ata"
832b75ed 119#endif
832b75ed 120
d008864d
GI
121#define ARGUSED(x) ((void)(x))
122
2127e193
GI
123// global variable holding byte count of allocated memory
124long long bytes;
ee38a438 125extern unsigned char failuretest_permissive;
832b75ed 126
2127e193 127/////////////////////////////////////////////////////////////////////////////
832b75ed 128
2127e193 129namespace os_freebsd { // No need to publish anything, name provided for Doxygen
832b75ed 130
2127e193
GI
131/////////////////////////////////////////////////////////////////////////////
132/// Implement shared open/close routines with old functions.
832b75ed 133
2127e193
GI
134class freebsd_smart_device
135: virtual public /*implements*/ smart_device
136{
137public:
138 explicit freebsd_smart_device(const char * mode)
139 : smart_device(never_called),
140 m_fd(-1), m_mode(mode) { }
832b75ed 141
2127e193 142 virtual ~freebsd_smart_device() throw();
832b75ed 143
2127e193 144 virtual bool is_open() const;
832b75ed 145
2127e193 146 virtual bool open();
832b75ed 147
2127e193 148 virtual bool close();
832b75ed 149
2127e193
GI
150protected:
151 /// Return filedesc for derived classes.
152 int get_fd() const
153 { return m_fd; }
832b75ed 154
eb07ddf2
GI
155 void set_fd(int fd)
156 { m_fd = fd; }
157
2127e193
GI
158private:
159 int m_fd; ///< filedesc, -1 if not open.
160 const char * m_mode; ///< Mode string for deviceopen().
161};
832b75ed 162
54965743
GI
163#ifdef __GLIBC__
164static inline void * reallocf(void *ptr, size_t size) {
165 void *rv = realloc(ptr, size);
f4ebf3d1 166 if((rv == NULL) && (size != 0))
54965743
GI
167 free(ptr);
168 return rv;
169 }
170#endif
2127e193
GI
171
172freebsd_smart_device::~freebsd_smart_device() throw()
a37e7145 173{
2127e193
GI
174 if (m_fd >= 0)
175 os_freebsd::freebsd_smart_device::close();
a37e7145
GG
176}
177
2127e193
GI
178// migration from the old_style
179unsigned char m_controller_type;
180unsigned char m_controller_port;
832b75ed 181
2127e193
GI
182// examples for smartctl
183static const char smartctl_examples[] =
54965743 184 "=================================================== SMARTCTL EXAMPLES =====\n\n"
2127e193
GI
185 " smartctl -a /dev/ad0 (Prints all SMART information)\n\n"
186 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/ad0\n"
187 " (Enables SMART on first disk)\n\n"
188 " smartctl -t long /dev/ad0 (Executes extended disk self-test)\n\n"
189 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/ad0\n"
190 " (Prints Self-Test & Attribute errors)\n"
191 " (Prints Self-Test & Attribute errors)\n\n"
192 " smartctl -a --device=3ware,2 /dev/twa0\n"
193 " smartctl -a --device=3ware,2 /dev/twe0\n"
ee38a438 194 " smartctl -a --device=3ware,2 /dev/tws0\n"
2127e193
GI
195 " (Prints all SMART information for ATA disk on\n"
196 " third port of first 3ware RAID controller)\n"
54965743
GI
197 " smartctl -a --device=cciss,0 /dev/ciss0\n"
198 " (Prints all SMART information for first disk \n"
199 " on Common Interface for SCSI-3 Support driver)\n"
f4e463df
GI
200 " smartctl -a --device=areca,3/1 /dev/arcmsr0\n"
201 " (Prints all SMART information for 3rd disk in the 1st enclosure \n"
d008864d 202 " on first ARECA RAID controller)\n"
54965743 203
2127e193 204 ;
832b75ed 205
2127e193
GI
206bool freebsd_smart_device::is_open() const
207{
208 return (m_fd >= 0);
209}
832b75ed 210
832b75ed 211
2127e193
GI
212bool freebsd_smart_device::open()
213{
2127e193 214 const char *dev = get_dev_name();
eb07ddf2
GI
215 if ((m_fd = ::open(dev,O_RDONLY))<0) {
216 set_err(errno);
2127e193
GI
217 return false;
218 }
219 return true;
220}
221
222bool freebsd_smart_device::close()
223{
2127e193 224 int failed = 0;
2127e193 225 // close device, if open
eb07ddf2
GI
226 if (is_open())
227 failed=::close(get_fd());
228
229 set_fd(-1);
54965743 230
54965743 231 if(failed) return false;
eb07ddf2 232 else return true;
2127e193
GI
233}
234
235/////////////////////////////////////////////////////////////////////////////
a23d5117 236/// Implement standard ATA support
2127e193
GI
237
238class freebsd_ata_device
a23d5117 239: public /*implements*/ ata_device,
2127e193
GI
240 public /*extends*/ freebsd_smart_device
241{
242public:
243 freebsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type);
a23d5117 244 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
2127e193 245
2127e193 246protected:
d008864d 247 virtual int do_cmd(struct ata_ioc_request* request, bool is_48bit_cmd);
2127e193
GI
248};
249
250freebsd_ata_device::freebsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type)
251: smart_device(intf, dev_name, "ata", req_type),
252 freebsd_smart_device("ATA")
253{
254}
255
d008864d 256int freebsd_ata_device::do_cmd( struct ata_ioc_request* request, bool is_48bit_cmd)
eb07ddf2 257{
ee38a438 258 int fd = get_fd(), ret;
d008864d 259 ARGUSED(is_48bit_cmd); // no support for 48 bit commands in the IOCATAREQUEST
ee38a438
GI
260 ret = ioctl(fd, IOCATAREQUEST, request);
261 if (ret) set_err(errno);
262 return ret;
eb07ddf2
GI
263}
264
a23d5117
GI
265
266
267bool freebsd_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
268{
d008864d
GI
269 bool ata_48bit = false; // no ata_48bit_support via IOCATAREQUEST
270 if(!strcmp("atacam",get_dev_type())) // enable for atacam interface
271 ata_48bit = true;
272
7f0798ef
GI
273 if (!ata_cmd_is_ok(in,
274 true, // data_out_support
275 true, // multi_sector_support
d008864d 276 ata_48bit)
ee38a438
GI
277 ) {
278 set_err(ENOSYS, "48-bit ATA commands not implemented for legacy controllers");
279 return false;
280 }
a23d5117
GI
281
282 struct ata_ioc_request request;
283 bzero(&request,sizeof(struct ata_ioc_request));
284
285 request.timeout=SCSI_TIMEOUT_DEFAULT;
286 request.u.ata.command=in.in_regs.command;
287 request.u.ata.feature=in.in_regs.features;
288
289 request.u.ata.count = in.in_regs.sector_count_16;
290 request.u.ata.lba = in.in_regs.lba_48;
291
292 switch (in.direction) {
293 case ata_cmd_in::no_data:
294 request.flags=ATA_CMD_CONTROL;
295 break;
296 case ata_cmd_in::data_in:
d008864d 297 request.flags=ATA_CMD_READ | ATA_CMD_CONTROL;
a23d5117
GI
298 request.data=(char *)in.buffer;
299 request.count=in.size;
300 break;
301 case ata_cmd_in::data_out:
d008864d 302 request.flags=ATA_CMD_WRITE | ATA_CMD_CONTROL;
a23d5117
GI
303 request.data=(char *)in.buffer;
304 request.count=in.size;
305 break;
306 default:
307 return set_err(ENOSYS);
308 }
d008864d
GI
309
310 clear_err();
a23d5117 311 errno = 0;
d008864d 312 if (do_cmd(&request, in.in_regs.is_48bit_cmd()))
ee38a438 313 return false;
a23d5117
GI
314 if (request.error)
315 return set_err(EIO, "request failed, error code 0x%02x", request.error);
316
317 out.out_regs.error = request.error;
318 out.out_regs.sector_count_16 = request.u.ata.count;
319 out.out_regs.lba_48 = request.u.ata.lba;
320
321
322 // Command specific processing
323 if (in.in_regs.command == ATA_SMART_CMD
324 && in.in_regs.features == ATA_SMART_STATUS
325 && in.out_needed.lba_high)
326 {
327 unsigned const char normal_lo=0x4f, normal_hi=0xc2;
328 unsigned const char failed_lo=0xf4, failed_hi=0x2c;
329
a23d5117
GI
330 // Cyl low and Cyl high unchanged means "Good SMART status"
331 if (!(out.out_regs.lba_mid==normal_lo && out.out_regs.lba_high==normal_hi)
332 // These values mean "Bad SMART status"
333 && !(out.out_regs.lba_mid==failed_lo && out.out_regs.lba_high==failed_hi))
334
335 {
336 // We haven't gotten output that makes sense; print out some debugging info
337 char buf[512];
ee38a438
GI
338 snprintf(buf, sizeof(buf),
339 "CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
a23d5117
GI
340 (int)request.u.ata.command,
341 (int)request.u.ata.feature,
342 (int)request.u.ata.count,
343 (int)((request.u.ata.lba) & 0xff),
344 (int)((request.u.ata.lba>>8) & 0xff),
345 (int)((request.u.ata.lba>>16) & 0xff),
346 (int)request.error);
347 printwarning(BAD_SMART,buf);
348 out.out_regs.lba_high = failed_hi;
349 out.out_regs.lba_mid = failed_lo;
350 }
351 }
352
353 return true;
354}
355
eb07ddf2
GI
356#if FREEBSDVER > 800100
357class freebsd_atacam_device : public freebsd_ata_device
358{
359public:
360 freebsd_atacam_device(smart_interface * intf, const char * dev_name, const char * req_type)
361 : smart_device(intf, dev_name, "atacam", req_type), freebsd_ata_device(intf, dev_name, req_type)
362 {}
363
364 virtual bool open();
365 virtual bool close();
366
367protected:
368 int m_fd;
369 struct cam_device *m_camdev;
370
d008864d 371 virtual int do_cmd( struct ata_ioc_request* request , bool is_48bit_cmd);
eb07ddf2
GI
372};
373
374bool freebsd_atacam_device::open(){
375 const char *dev = get_dev_name();
376
377 if ((m_camdev = cam_open_device(dev, O_RDWR)) == NULL) {
378 set_err(errno);
379 return false;
380 }
381 set_fd(m_camdev->fd);
382 return true;
383}
384
385bool freebsd_atacam_device::close(){
386 cam_close_device(m_camdev);
387 set_fd(-1);
388 return true;
389}
390
d008864d 391int freebsd_atacam_device::do_cmd( struct ata_ioc_request* request, bool is_48bit_cmd)
eb07ddf2
GI
392{
393 union ccb ccb;
394 int camflags;
395
ee38a438
GI
396 // FIXME:
397 // 48bit commands are broken in ATACAM before r242422/HEAD
398 // and may cause system hang
399 // Waiting for MFC to make sure that bug is fixed,
400 // later version check needs to be added
401 if(!strcmp("ata",m_camdev->sim_name) && is_48bit_cmd) {
402 set_err(ENOSYS, "48-bit ATA commands not implemented for legacy controllers");
403 return -1;
404 }
405
eb07ddf2
GI
406 memset(&ccb, 0, sizeof(ccb));
407
408 if (request->count == 0)
409 camflags = CAM_DIR_NONE;
d008864d 410 else if (request->flags & ATA_CMD_READ)
eb07ddf2
GI
411 camflags = CAM_DIR_IN;
412 else
413 camflags = CAM_DIR_OUT;
414
415 cam_fill_ataio(&ccb.ataio,
416 0,
417 NULL,
418 camflags,
419 MSG_SIMPLE_Q_TAG,
420 (u_int8_t*)request->data,
421 request->count,
422 request->timeout * 1000); // timeout in seconds
423
ee38a438
GI
424 ccb.ataio.cmd.flags = CAM_ATAIO_NEEDRESULT |
425 (is_48bit_cmd ? CAM_ATAIO_48BIT : 0);
eb07ddf2 426 // ata_28bit_cmd
eb07ddf2
GI
427 ccb.ataio.cmd.command = request->u.ata.command;
428 ccb.ataio.cmd.features = request->u.ata.feature;
429 ccb.ataio.cmd.lba_low = request->u.ata.lba;
430 ccb.ataio.cmd.lba_mid = request->u.ata.lba >> 8;
431 ccb.ataio.cmd.lba_high = request->u.ata.lba >> 16;
d008864d
GI
432 // ata_48bit cmd
433 ccb.ataio.cmd.lba_low_exp = request->u.ata.lba >> 24;
434 ccb.ataio.cmd.lba_mid_exp = request->u.ata.lba >> 32;
435 ccb.ataio.cmd.lba_high_exp = request->u.ata.lba >> 40;
eb07ddf2
GI
436 ccb.ataio.cmd.device = 0x40 | ((request->u.ata.lba >> 24) & 0x0f);
437 ccb.ataio.cmd.sector_count = request->u.ata.count;
d008864d 438 ccb.ataio.cmd.sector_count_exp = request->u.ata.count >> 8;;
eb07ddf2
GI
439
440 ccb.ccb_h.flags |= CAM_DEV_QFRZDIS;
441
442 if (cam_send_ccb(m_camdev, &ccb) < 0) {
ee38a438 443 set_err(EIO, "cam_send_ccb failed");
eb07ddf2
GI
444 return -1;
445 }
446
cfbba5b9
GI
447 if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
448 cam_error_print(m_camdev, &ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
ee38a438 449 set_err(EIO);
cfbba5b9
GI
450 return -1;
451 }
eb07ddf2 452
d008864d
GI
453 request->u.ata.lba =
454 ((u_int64_t)(ccb.ataio.res.lba_low)) |
455 ((u_int64_t)(ccb.ataio.res.lba_mid) << 8) |
456 ((u_int64_t)(ccb.ataio.res.lba_high) << 16) |
457 ((u_int64_t)(ccb.ataio.res.lba_low_exp) << 24) |
458 ((u_int64_t)(ccb.ataio.res.lba_mid_exp) << 32) |
459 ((u_int64_t)(ccb.ataio.res.lba_high_exp) << 40);
460
461 request->u.ata.count = ccb.ataio.res.sector_count | (ccb.ataio.res.sector_count_exp << 8);
462 request->error = ccb.ataio.res.error;
463
cfbba5b9 464 return 0;
eb07ddf2
GI
465}
466
467#endif
468
2127e193 469/////////////////////////////////////////////////////////////////////////////
ee38a438 470/// Implement AMCC/3ware RAID support
2127e193
GI
471
472class freebsd_escalade_device
ee38a438 473: public /*implements*/ ata_device,
2127e193
GI
474 public /*extends*/ freebsd_smart_device
475{
476public:
477 freebsd_escalade_device(smart_interface * intf, const char * dev_name,
478 int escalade_type, int disknum);
479
480protected:
ee38a438 481 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
eb07ddf2 482 virtual bool open();
2127e193
GI
483
484private:
485 int m_escalade_type; ///< Type string for escalade_command_interface().
486 int m_disknum; ///< Disk number.
487};
488
489freebsd_escalade_device::freebsd_escalade_device(smart_interface * intf, const char * dev_name,
490 int escalade_type, int disknum)
491: smart_device(intf, dev_name, "3ware", "3ware"),
492 freebsd_smart_device(
493 escalade_type==CONTROLLER_3WARE_9000_CHAR ? "ATA_3WARE_9000" :
494 escalade_type==CONTROLLER_3WARE_678K_CHAR ? "ATA_3WARE_678K" :
495 /* CONTROLLER_3WARE_678K */ "ATA" ),
496 m_escalade_type(escalade_type), m_disknum(disknum)
497{
498 set_info().info_name = strprintf("%s [3ware_disk_%02d]", dev_name, disknum);
499}
500
eb07ddf2
GI
501bool freebsd_escalade_device::open()
502{
503 const char *dev = get_dev_name();
504 int fd;
505
506 if ((fd = ::open(dev,O_RDWR))<0) {
507 set_err(errno);
508 return false;
509 }
510 set_fd(fd);
511 return true;
512}
513
ee38a438 514bool freebsd_escalade_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
2127e193 515{
54965743
GI
516 // to hold true file descriptor
517 int fd = get_fd();
2127e193 518
ee38a438
GI
519 if (!ata_cmd_is_ok(in,
520 true, // data_out_support
521 false, // TODO: multi_sector_support
522 true) // ata_48bit_support
523 )
524 return false;
525
2127e193
GI
526 struct twe_usercommand* cmd_twe = NULL;
527 TW_OSLI_IOCTL_NO_DATA_BUF* cmd_twa = NULL;
528 TWE_Command_ATA* ata = NULL;
529
530 // Used by both the SCSI and char interfaces
531 char ioctl_buffer[TW_IOCTL_BUFFER_SIZE];
532
533 if (m_disknum < 0) {
534 printwarning(NO_DISK_3WARE,NULL);
535 return -1;
536 }
537
2127e193
GI
538 memset(ioctl_buffer, 0, TW_IOCTL_BUFFER_SIZE);
539
540 if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) {
541 cmd_twa = (TW_OSLI_IOCTL_NO_DATA_BUF*)ioctl_buffer;
542 cmd_twa->pdata = ((TW_OSLI_IOCTL_WITH_PAYLOAD*)cmd_twa)->payload.data_buf;
ee38a438
GI
543 cmd_twa->driver_pkt.buffer_length = in.size;
544 // using "old" packet format to speak with SATA devices
2127e193
GI
545 ata = (TWE_Command_ATA*)&cmd_twa->cmd_pkt.command.cmd_pkt_7k;
546 } else if (m_escalade_type==CONTROLLER_3WARE_678K_CHAR) {
547 cmd_twe = (struct twe_usercommand*)ioctl_buffer;
548 ata = &cmd_twe->tu_command.ata;
549 } else {
ee38a438
GI
550 return set_err(ENOSYS,
551 "Unrecognized escalade_type %d in linux_3ware_command_interface(disk %d)\n"
552 "Please contact " PACKAGE_BUGREPORT "\n", (int)m_escalade_type, m_disknum);
2127e193
GI
553 }
554
555 ata->opcode = TWE_OP_ATA_PASSTHROUGH;
556
557 // Same for (almost) all commands - but some reset below
558 ata->request_id = 0xFF;
559 ata->unit = m_disknum;
ee38a438 560 ata->status = 0;
2127e193 561 ata->flags = 0x1;
ee38a438
GI
562 ata->size = 0x5; // TODO: multisector support
563 // Set registers
564 {
565 const ata_in_regs_48bit & r = in.in_regs;
566 ata->features = r.features_16;
567 ata->sector_count = r.sector_count_16;
568 ata->sector_num = r.lba_low_16;
569 ata->cylinder_lo = r.lba_mid_16;
570 ata->cylinder_hi = r.lba_high_16;
571 ata->drive_head = r.device;
572 ata->command = r.command;
573 }
54965743 574
2127e193
GI
575 // Is this a command that reads or returns 512 bytes?
576 // passthru->param values are:
577 // 0x0 - non data command without TFR write check,
578 // 0x8 - non data command with TFR write check,
579 // 0xD - data command that returns data to host from device
580 // 0xF - data command that writes data from host to device
581 // passthru->size values are 0x5 for non-data and 0x07 for data
ee38a438
GI
582 bool readdata = false;
583 if (in.direction == ata_cmd_in::data_in) {
2127e193 584 if (m_escalade_type==CONTROLLER_3WARE_678K_CHAR) {
ee38a438 585 cmd_twe->tu_data = in.buffer;
2127e193
GI
586 cmd_twe->tu_size = 512;
587 }
ee38a438
GI
588
589 readdata=true;
590 ata->sgl_offset = 0x5;
2127e193 591 ata->param = 0xD;
2127e193
GI
592 // For 64-bit to work correctly, up the size of the command packet
593 // in dwords by 1 to account for the 64-bit single sgl 'address'
594 // field. Note that this doesn't agree with the typedefs but it's
595 // right (agree with kernel driver behavior/typedefs).
ee38a438 596 // if (sizeof(long)==8)
2127e193
GI
597 // ata->size++;
598 }
ee38a438 599 else if (in.direction == ata_cmd_in::no_data) {
2127e193 600 // Non data command -- but doesn't use large sector
ee38a438
GI
601 // count register values.
602 ata->sgl_offset = 0x0;
2127e193
GI
603 ata->param = 0x8;
604 ata->sector_count = 0x0;
605 }
ee38a438
GI
606 else if (in.direction == ata_cmd_in::data_out) {
607 ata->sgl_offset = 0x5;
608 ata->param = 0xF; // PIO data write
609 if (m_escalade_type==CONTROLLER_3WARE_678K_CHAR) {
610 cmd_twe->tu_data = in.buffer;
611 cmd_twe->tu_size = 512;
612 }
613 else if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) {
614 memcpy(cmd_twa->pdata, in.buffer, in.size);
615 }
616 }
617 else
618 return set_err(EINVAL);
54965743 619
ee38a438
GI
620 // 3WARE controller can NOT have packet device internally
621 if (in.in_regs.command == ATA_IDENTIFY_PACKET_DEVICE) {
622 return set_err(ENODEV, "No drive on port %d", m_disknum);
2127e193
GI
623 }
624
625 // Now send the command down through an ioctl()
ee38a438 626 int ioctlreturn;
2127e193 627 if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) {
eb07ddf2 628 ioctlreturn=ioctl(fd,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa);
2127e193 629 } else {
eb07ddf2 630 ioctlreturn=ioctl(fd,TWEIO_COMMAND,cmd_twe);
2127e193
GI
631 }
632
633 // Deal with the different error cases
634 if (ioctlreturn) {
ee38a438 635 return set_err(EIO);
2127e193 636 }
54965743 637
2127e193
GI
638 // See if the ATA command failed. Now that we have returned from
639 // the ioctl() call, if passthru is valid, then:
640 // - ata->status contains the 3ware controller STATUS
641 // - ata->command contains the ATA STATUS register
642 // - ata->features contains the ATA ERROR register
643 //
644 // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS
645 // If bit 0 (error bit) is set, then ATA ERROR register is valid.
646 // While we *might* decode the ATA ERROR register, at the moment it
647 // doesn't make much sense: we don't care in detail why the error
648 // happened.
54965743 649
2127e193 650 if (ata->status || (ata->command & 0x21)) {
ee38a438
GI
651 if (scsi_debugmode)
652 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);
653 return set_err(EIO);
2127e193 654 }
54965743 655
2127e193
GI
656 // If this is a read data command, copy data to output buffer
657 if (readdata) {
658 if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR)
ee38a438
GI
659 memcpy(in.buffer, cmd_twa->pdata, in.size);
660 else if(m_escalade_type==CONTROLLER_3WARE_678K_CHAR) {
661 memcpy(in.buffer, cmd_twe->tu_data, in.size); // untested
662 }
2127e193 663 }
ee38a438
GI
664 // Return register values
665 if (ata) {
666 ata_out_regs_48bit & r = out.out_regs;
667 r.error = ata->features;
668 r.sector_count_16 = ata->sector_count;
669 r.lba_low_16 = ata->sector_num;
670 r.lba_mid_16 = ata->cylinder_lo;
671 r.lba_high_16 = ata->cylinder_hi;
672 r.device = ata->drive_head;
673 r.status = ata->command;
2127e193 674 }
2127e193 675 // look for nonexistent devices/ports
ee38a438
GI
676 if (in.in_regs.command == ATA_IDENTIFY_DEVICE
677 && !nonempty((unsigned char *)in.buffer, in.size)) {
678 return set_err(ENODEV, "No drive on port %d", m_disknum);
2127e193 679 }
ee38a438 680 return true;
2127e193
GI
681}
682
683
684/////////////////////////////////////////////////////////////////////////////
685/// Implement Highpoint RAID support with old functions
686
687class freebsd_highpoint_device
688: public /*implements*/ ata_device_with_command_set,
689 public /*extends*/ freebsd_smart_device
690{
691public:
692 freebsd_highpoint_device(smart_interface * intf, const char * dev_name,
693 unsigned char controller, unsigned char channel, unsigned char port);
694
695protected:
696 virtual int ata_command_interface(smart_command_set command, int select, char * data);
eb07ddf2 697 virtual bool open();
2127e193
GI
698
699private:
700 unsigned char m_hpt_data[3]; ///< controller/channel/port
701};
702
703
704freebsd_highpoint_device::freebsd_highpoint_device(smart_interface * intf, const char * dev_name,
705 unsigned char controller, unsigned char channel, unsigned char port)
706: smart_device(intf, dev_name, "hpt", "hpt"),
707 freebsd_smart_device("ATA")
708{
709 m_hpt_data[0] = controller; m_hpt_data[1] = channel; m_hpt_data[2] = port;
710 set_info().info_name = strprintf("%s [hpt_disk_%u/%u/%u]", dev_name, m_hpt_data[0], m_hpt_data[1], m_hpt_data[2]);
711}
712
eb07ddf2
GI
713bool freebsd_highpoint_device::open()
714{
715 const char *dev = get_dev_name();
716 int fd;
717
718 if ((fd = ::open(dev,O_RDWR))<0) {
719 set_err(errno);
720 return false;
721 }
722 set_fd(fd);
723 return true;
724}
725
2127e193
GI
726int freebsd_highpoint_device::ata_command_interface(smart_command_set command, int select, char * data)
727{
54965743 728 int fd=get_fd();
2127e193 729 int ids[2];
2127e193
GI
730 HPT_IOCTL_PARAM param;
731 HPT_CHANNEL_INFO_V2 info;
732 unsigned char* buff[512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER)];
733 PHPT_PASS_THROUGH_HEADER pide_pt_hdr, pide_pt_hdr_out;
734
2127e193
GI
735 // get internal deviceid
736 ids[0] = m_hpt_data[0] - 1;
737 ids[1] = m_hpt_data[1] - 1;
738
739 memset(&param, 0, sizeof(HPT_IOCTL_PARAM));
740
741 param.magic = HPT_IOCTL_MAGIC;
742 param.ctrl_code = HPT_IOCTL_GET_CHANNEL_INFO_V2;
743 param.in = (unsigned char *)ids;
744 param.in_size = sizeof(unsigned int) * 2;
745 param.out = (unsigned char *)&info;
746 param.out_size = sizeof(HPT_CHANNEL_INFO_V2);
747
748 if (m_hpt_data[2]==1) {
749 param.ctrl_code = HPT_IOCTL_GET_CHANNEL_INFO;
750 param.out_size = sizeof(HPT_CHANNEL_INFO);
751 }
eb07ddf2 752 if (ioctl(fd, HPT_DO_IOCONTROL, &param)!=0 ||
2127e193
GI
753 info.devices[m_hpt_data[2]-1]==0) {
754 return -1;
755 }
756
757 // perform smart action
758 memset(buff, 0, 512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER));
759 pide_pt_hdr = (PHPT_PASS_THROUGH_HEADER)buff;
760
761 pide_pt_hdr->lbamid = 0x4f;
762 pide_pt_hdr->lbahigh = 0xc2;
763 pide_pt_hdr->command = ATA_SMART_CMD;
764 pide_pt_hdr->id = info.devices[m_hpt_data[2] - 1];
765
766 switch (command){
767 case READ_VALUES:
768 pide_pt_hdr->feature=ATA_SMART_READ_VALUES;
769 pide_pt_hdr->protocol=HPT_READ;
770 break;
771 case READ_THRESHOLDS:
772 pide_pt_hdr->feature=ATA_SMART_READ_THRESHOLDS;
773 pide_pt_hdr->protocol=HPT_READ;
774 break;
775 case READ_LOG:
776 pide_pt_hdr->feature=ATA_SMART_READ_LOG_SECTOR;
777 pide_pt_hdr->lbalow=select;
778 pide_pt_hdr->protocol=HPT_READ;
779 break;
780 case IDENTIFY:
781 pide_pt_hdr->command=ATA_IDENTIFY_DEVICE;
782 pide_pt_hdr->protocol=HPT_READ;
783 break;
784 case ENABLE:
785 pide_pt_hdr->feature=ATA_SMART_ENABLE;
786 break;
787 case DISABLE:
788 pide_pt_hdr->feature=ATA_SMART_DISABLE;
789 break;
790 case AUTO_OFFLINE:
791 pide_pt_hdr->feature=ATA_SMART_AUTO_OFFLINE;
792 pide_pt_hdr->sectorcount=select;
793 break;
794 case AUTOSAVE:
795 pide_pt_hdr->feature=ATA_SMART_AUTOSAVE;
796 pide_pt_hdr->sectorcount=select;
797 break;
798 case IMMEDIATE_OFFLINE:
799 pide_pt_hdr->feature=ATA_SMART_IMMEDIATE_OFFLINE;
800 pide_pt_hdr->lbalow=select;
801 break;
802 case STATUS_CHECK:
803 case STATUS:
804 pide_pt_hdr->feature=ATA_SMART_STATUS;
805 break;
806 case CHECK_POWER_MODE:
807 pide_pt_hdr->command=ATA_CHECK_POWER_MODE;
808 break;
809 case WRITE_LOG:
810 memcpy(buff+sizeof(HPT_PASS_THROUGH_HEADER), data, 512);
811 pide_pt_hdr->feature=ATA_SMART_WRITE_LOG_SECTOR;
812 pide_pt_hdr->lbalow=select;
813 pide_pt_hdr->protocol=HPT_WRITE;
814 break;
815 default:
816 pout("Unrecognized command %d in highpoint_command_interface()\n"
817 "Please contact " PACKAGE_BUGREPORT "\n", command);
818 errno=ENOSYS;
819 return -1;
820 }
821 if (pide_pt_hdr->protocol!=0) {
822 pide_pt_hdr->sectors = 1;
823 pide_pt_hdr->sectorcount = 1;
824 }
825
826 memset(&param, 0, sizeof(HPT_IOCTL_PARAM));
827
828 param.magic = HPT_IOCTL_MAGIC;
829 param.ctrl_code = HPT_IOCTL_IDE_PASS_THROUGH;
830 param.in = (unsigned char *)buff;
831 param.in_size = sizeof(HPT_PASS_THROUGH_HEADER) + (pide_pt_hdr->protocol==HPT_READ ? 0 : pide_pt_hdr->sectors * 512);
832 param.out = (unsigned char *)buff+param.in_size;
833 param.out_size = sizeof(HPT_PASS_THROUGH_HEADER) + (pide_pt_hdr->protocol==HPT_READ ? pide_pt_hdr->sectors * 512 : 0);
834
835 pide_pt_hdr_out = (PHPT_PASS_THROUGH_HEADER)param.out;
836
eb07ddf2 837 if ((ioctl(fd, HPT_DO_IOCONTROL, &param)!=0) ||
2127e193
GI
838 (pide_pt_hdr_out->command & 1)) {
839 return -1;
840 }
841
54965743
GI
842 if (command==STATUS_CHECK)
843 {
2127e193
GI
844 unsigned const char normal_lo=0x4f, normal_hi=0xc2;
845 unsigned const char failed_lo=0xf4, failed_hi=0x2c;
846 unsigned char low,high;
847
848 high = pide_pt_hdr_out->lbahigh;
849 low = pide_pt_hdr_out->lbamid;
850
851 // Cyl low and Cyl high unchanged means "Good SMART status"
852 if (low==normal_lo && high==normal_hi)
853 return 0;
854
855 // These values mean "Bad SMART status"
856 if (low==failed_lo && high==failed_hi)
857 return 1;
858
859 // We haven't gotten output that makes sense; print out some debugging info
860 char buf[512];
ee38a438
GI
861 snprintf(buf, sizeof(buf),
862 "CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
2127e193
GI
863 (int)pide_pt_hdr_out->command,
864 (int)pide_pt_hdr_out->feature,
865 (int)pide_pt_hdr_out->sectorcount,
866 (int)pide_pt_hdr_out->lbalow,
867 (int)pide_pt_hdr_out->lbamid,
868 (int)pide_pt_hdr_out->lbahigh,
869 (int)pide_pt_hdr_out->sectors);
870 printwarning(BAD_SMART,buf);
871 }
872 else if (command==CHECK_POWER_MODE)
873 data[0] = pide_pt_hdr_out->sectorcount & 0xff;
874 else if (pide_pt_hdr->protocol==HPT_READ)
54965743
GI
875 memcpy(data, (unsigned char *)buff + 2 * sizeof(HPT_PASS_THROUGH_HEADER),
876 pide_pt_hdr->sectors * 512);
2127e193
GI
877 return 0;
878}
879
880
881/////////////////////////////////////////////////////////////////////////////
e165493d 882/// Standard SCSI support
2127e193
GI
883
884class freebsd_scsi_device
885: public /*implements*/ scsi_device,
886 public /*extends*/ freebsd_smart_device
887{
888public:
889 freebsd_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type);
890
891 virtual smart_device * autodetect_open();
892
893 virtual bool scsi_pass_through(scsi_cmnd_io * iop);
eb07ddf2
GI
894
895 virtual bool open();
896
897 virtual bool close();
898
899private:
900 int m_fd;
901 struct cam_device *m_camdev;
2127e193
GI
902};
903
eb07ddf2
GI
904bool freebsd_scsi_device::open(){
905 const char *dev = get_dev_name();
906
907 if ((m_camdev = cam_open_device(dev, O_RDWR)) == NULL) {
908 set_err(errno);
909 return false;
910 }
911 set_fd(m_camdev->fd);
912 return true;
913}
914
915bool freebsd_scsi_device::close(){
916 cam_close_device(m_camdev);
917 set_fd(-1);
918 return true;
919}
920
2127e193
GI
921freebsd_scsi_device::freebsd_scsi_device(smart_interface * intf,
922 const char * dev_name, const char * req_type)
923: smart_device(intf, dev_name, "scsi", req_type),
924 freebsd_smart_device("SCSI")
925{
926}
927
eb07ddf2
GI
928
929bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
2127e193 930{
cfbba5b9 931 int report=scsi_debugmode;
2127e193 932 union ccb *ccb;
54965743
GI
933
934 if (report > 0) {
935 unsigned int k;
936 const unsigned char * ucp = iop->cmnd;
937 const char * np;
938
939 np = scsi_get_opcode_name(ucp[0]);
940 pout(" [%s: ", np ? np : "<unknown opcode>");
941 for (k = 0; k < iop->cmnd_len; ++k)
942 pout("%02x ", ucp[k]);
943 if ((report > 1) &&
944 (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
945 int trunc = (iop->dxfer_len > 256) ? 1 : 0;
946
947 pout("]\n Outgoing data, len=%d%s:\n", (int)iop->dxfer_len,
948 (trunc ? " [only first 256 bytes shown]" : ""));
949 dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
950 }
951 else
952 pout("]");
953 }
2127e193 954
eb07ddf2
GI
955 if(m_camdev==NULL) {
956 warnx("error: camdev=0!");
54965743 957 return -ENOTTY;
2127e193
GI
958 }
959
eb07ddf2 960 if (!(ccb = cam_getccb(m_camdev))) {
2127e193
GI
961 warnx("error allocating ccb");
962 return -ENOMEM;
963 }
d008864d
GI
964 // mfi SAT layer is known to be buggy
965 if(!strcmp("mfi",m_camdev->sim_name)) {
966 if (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 || iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16) {
967 // Controller does not return ATA output registers in SAT sense data
968 if (iop->cmnd[2] & (1 << 5)) // chk_cond
969 return set_err(ENOSYS, "ATA return descriptor not supported by controller firmware");
970 }
971 // SMART WRITE LOG SECTOR causing media errors
ee38a438
GI
972 if ((iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16
973 && iop->cmnd[14] == ATA_SMART_CMD && iop->cmnd[3]==0 &&
974 iop->cmnd[4] == ATA_SMART_WRITE_LOG_SECTOR) ||
975 (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12
976 && iop->cmnd[9] == ATA_SMART_CMD && iop->cmnd[3] == ATA_SMART_WRITE_LOG_SECTOR))
977 {
978 if(!failuretest_permissive)
979 return set_err(ENOSYS, "SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force");
980 }
d008864d 981 }
2127e193
GI
982 // clear out structure, except for header that was filled in for us
983 bzero(&(&ccb->ccb_h)[1],
54965743 984 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2127e193
GI
985
986 cam_fill_csio(&ccb->csio,
54965743
GI
987 /*retrires*/ 1,
988 /*cbfcnp*/ NULL,
989 /* flags */ (iop->dxfer_dir == DXFER_NONE ? CAM_DIR_NONE :(iop->dxfer_dir == DXFER_FROM_DEVICE ? CAM_DIR_IN : CAM_DIR_OUT)),
990 /* tagaction */ MSG_SIMPLE_Q_TAG,
991 /* dataptr */ iop->dxferp,
992 /* datalen */ iop->dxfer_len,
993 /* senselen */ iop->max_sense_len,
994 /* cdblen */ iop->cmnd_len,
995 /* timout (converted to seconds) */ iop->timeout*1000);
2127e193
GI
996 memcpy(ccb->csio.cdb_io.cdb_bytes,iop->cmnd,iop->cmnd_len);
997
eb07ddf2 998 if (cam_send_ccb(m_camdev,ccb) < 0) {
2127e193 999 warn("error sending SCSI ccb");
eb07ddf2 1000 cam_error_print(m_camdev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
2127e193
GI
1001 cam_freeccb(ccb);
1002 return -EIO;
1003 }
1004
54965743 1005 if (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR)) {
eb07ddf2 1006 cam_error_print(m_camdev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
2127e193
GI
1007 cam_freeccb(ccb);
1008 return -EIO;
1009 }
1010
1011 if (iop->sensep) {
d008864d
GI
1012 iop->resp_sense_len = ccb->csio.sense_len - ccb->csio.sense_resid;
1013 memcpy(iop->sensep,&(ccb->csio.sense_data),iop->resp_sense_len);
2127e193
GI
1014 }
1015
1016 iop->scsi_status = ccb->csio.scsi_status;
1017
1018 cam_freeccb(ccb);
54965743 1019
2127e193
GI
1020 if (report > 0) {
1021 int trunc;
1022
1023 pout(" status=0\n");
1024 trunc = (iop->dxfer_len > 256) ? 1 : 0;
54965743 1025
2127e193 1026 pout(" Incoming data, len=%d%s:\n", (int)iop->dxfer_len,
54965743 1027 (trunc ? " [only first 256 bytes shown]" : ""));
2127e193
GI
1028 dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
1029 }
54965743 1030
ee38a438
GI
1031 // mfip replacing PDT of the device so response does not make a sense
1032 // this sets PDT to 00h - direct-access block device
1033 if((!strcmp("mfi", m_camdev->sim_name) || !strcmp("mpt", m_camdev->sim_name))
1034 && iop->cmnd[0] == INQUIRY) {
1035 if (report > 0) {
1036 pout("device on %s controller, patching PDT\n", m_camdev->sim_name);
1037 }
1038 iop->dxferp[0] = iop->dxferp[0] & 0xe0;
1039 }
1040
2127e193
GI
1041 return true;
1042}
1043
1044
d008864d
GI
1045/////////////////////////////////////////////////////////////////////////////
1046/// Areca RAID support
1047
ee38a438
GI
1048///////////////////////////////////////////////////////////////////
1049// SATA(ATA) device behind Areca RAID Controller
1050class freebsd_areca_ata_device
1051: public /*implements*/ areca_ata_device,
d008864d
GI
1052 public /*extends*/ freebsd_smart_device
1053{
1054public:
ee38a438
GI
1055 freebsd_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
1056 virtual smart_device * autodetect_open();
1057 virtual bool arcmsr_lock();
1058 virtual bool arcmsr_unlock();
1059 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop);
1060};
d008864d 1061
ee38a438
GI
1062///////////////////////////////////////////////////////////////////
1063// SAS(SCSI) device behind Areca RAID Controller
1064class freebsd_areca_scsi_device
1065: public /*implements*/ areca_scsi_device,
1066 public /*extends*/ freebsd_smart_device
1067{
1068public:
1069 freebsd_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
1070 virtual smart_device * autodetect_open();
1071 virtual bool arcmsr_lock();
1072 virtual bool arcmsr_unlock();
1073 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop);
d008864d
GI
1074};
1075
1076
ee38a438
GI
1077// Areca RAID Controller(SATA Disk)
1078freebsd_areca_ata_device::freebsd_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
1079: smart_device(intf, dev_name, "areca", "areca"),
1080 freebsd_smart_device("ATA")
1081{
1082 set_disknum(disknum);
1083 set_encnum(encnum);
1084 set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
1085}
1086
1087
1088smart_device * freebsd_areca_ata_device::autodetect_open()
d008864d 1089{
ee38a438
GI
1090 int is_ata = 1;
1091
1092 // autodetect device type
1093 is_ata = arcmsr_get_dev_type();
1094 if(is_ata < 0)
1095 {
1096 set_err(EIO);
1097 return this;
1098 }
1099
1100 if(is_ata == 1)
1101 {
1102 // SATA device
1103 return this;
1104 }
1105
1106 // SAS device
1107 smart_device_auto_ptr newdev(new freebsd_areca_scsi_device(smi(), get_dev_name(), get_disknum(), get_encnum()));
1108 close();
1109 delete this;
1110 newdev->open(); // TODO: Can possibly pass open fd
1111
1112 return newdev.release();
1113}
1114
1115int freebsd_areca_ata_device::arcmsr_do_scsi_io(struct scsi_cmnd_io * iop)
d008864d 1116{
ee38a438
GI
1117 int ioctlreturn = 0;
1118
1119 if(!is_open()) {
1120 if(!open()){
1121 }
1122 }
d008864d 1123
ee38a438
GI
1124 ioctlreturn = ioctl(get_fd(), ((sSRB_BUFFER *)(iop->dxferp))->srbioctl.ControlCode, iop->dxferp);
1125 if (ioctlreturn)
1126 {
1127 // errors found
1128 return -1;
1129 }
d008864d 1130
ee38a438
GI
1131 return ioctlreturn;
1132}
d008864d 1133
ee38a438 1134bool freebsd_areca_ata_device::arcmsr_lock()
d008864d 1135{
ee38a438 1136 return true;
d008864d
GI
1137}
1138
1139
ee38a438 1140bool freebsd_areca_ata_device::arcmsr_unlock()
d008864d 1141{
ee38a438 1142 return true;
d008864d
GI
1143}
1144
1145
ee38a438
GI
1146// Areca RAID Controller(SAS Device)
1147freebsd_areca_scsi_device::freebsd_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
d008864d 1148: smart_device(intf, dev_name, "areca", "areca"),
ee38a438 1149 freebsd_smart_device("SCSI")
d008864d 1150{
ee38a438
GI
1151 set_disknum(disknum);
1152 set_encnum(encnum);
f4e463df 1153 set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
d008864d
GI
1154}
1155
ee38a438
GI
1156smart_device * freebsd_areca_scsi_device::autodetect_open()
1157{
1158 return this;
1159}
1160
1161int freebsd_areca_scsi_device::arcmsr_do_scsi_io(struct scsi_cmnd_io * iop)
1162{
1163 int ioctlreturn = 0;
1164
1165 if(!is_open()) {
1166 if(!open()){
1167 }
1168 }
1169 ioctlreturn = ioctl(get_fd(), ((sSRB_BUFFER *)(iop->dxferp))->srbioctl.ControlCode, iop->dxferp);
1170 if (ioctlreturn)
1171 {
1172 // errors found
1173 return -1;
1174 }
1175
1176 return ioctlreturn;
1177}
1178
1179bool freebsd_areca_scsi_device::arcmsr_lock()
d008864d 1180{
ee38a438 1181 return true;
d008864d
GI
1182}
1183
1184
ee38a438
GI
1185bool freebsd_areca_scsi_device::arcmsr_unlock()
1186{
1187 return true;
1188}
1189
d008864d 1190
2127e193
GI
1191/////////////////////////////////////////////////////////////////////////////
1192/// Implement CCISS RAID support with old functions
1193
1194class freebsd_cciss_device
1195: public /*implements*/ scsi_device,
1196 public /*extends*/ freebsd_smart_device
1197{
1198public:
1199 freebsd_cciss_device(smart_interface * intf, const char * name, unsigned char disknum);
1200
1201 virtual bool scsi_pass_through(scsi_cmnd_io * iop);
eb07ddf2 1202 virtual bool open();
2127e193
GI
1203
1204private:
1205 unsigned char m_disknum; ///< Disk number.
1206};
1207
eb07ddf2
GI
1208bool freebsd_cciss_device::open()
1209{
1210 const char *dev = get_dev_name();
1211 int fd;
eb07ddf2
GI
1212 if ((fd = ::open(dev,O_RDWR))<0) {
1213 set_err(errno);
1214 return false;
1215 }
1216 set_fd(fd);
1217 return true;
1218}
2127e193
GI
1219
1220freebsd_cciss_device::freebsd_cciss_device(smart_interface * intf,
1221 const char * dev_name, unsigned char disknum)
1222: smart_device(intf, dev_name, "cciss", "cciss"),
1223 freebsd_smart_device("SCSI"),
1224 m_disknum(disknum)
1225{
1226 set_info().info_name = strprintf("%s [cciss_disk_%02d]", dev_name, disknum);
1227}
1228
1229bool freebsd_cciss_device::scsi_pass_through(scsi_cmnd_io * iop)
1230{
cfbba5b9 1231 int status = cciss_io_interface(get_fd(), m_disknum, iop, scsi_debugmode);
eb07ddf2
GI
1232 if (status < 0)
1233 return set_err(-status);
1234 return true;
eb07ddf2 1235 // not reached
2127e193
GI
1236 return true;
1237}
1238
1239
1240/////////////////////////////////////////////////////////////////////////////
1241/// SCSI open with autodetection support
1242
1243smart_device * freebsd_scsi_device::autodetect_open()
1244{
1245 // Open device
1246 if (!open())
1247 return this;
1248
1249 // No Autodetection if device type was specified by user
1250 if (*get_req_type())
1251 return this;
1252
1253 // The code below is based on smartd.cpp:SCSIFilterKnown()
1254
1255 // Get INQUIRY
1256 unsigned char req_buff[64] = {0, };
1257 int req_len = 36;
1258 if (scsiStdInquiry(this, req_buff, req_len)) {
1259 // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
1260 // watch this spot ... other devices could lock up here
1261 req_len = 64;
1262 if (scsiStdInquiry(this, req_buff, req_len)) {
1263 // device doesn't like INQUIRY commands
1264 close();
1265 set_err(EIO, "INQUIRY failed");
1266 return this;
1267 }
1268 }
1269
1270 int avail_len = req_buff[4] + 5;
1271 int len = (avail_len < req_len ? avail_len : req_len);
1272 if (len < 36)
54965743 1273 return this;
2127e193
GI
1274
1275 // Use INQUIRY to detect type
2127e193 1276
bed94269 1277 // 3ware ?
ee38a438
GI
1278 if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4) ||
1279 !strcmp("tws",m_camdev->sim_name) || !strcmp("twa",m_camdev->sim_name)) {
bed94269 1280 close();
ee38a438
GI
1281 set_err(EINVAL, "3ware/LSI controller, please try adding '-d 3ware,N',\n"
1282 "you may need to replace %s with /dev/twaN, /dev/tweN or /dev/twsN", get_dev_name());
bed94269
GI
1283 return this;
1284 }
1285
d008864d 1286 // SAT or USB, skip MFI controllers because of bugs
bed94269
GI
1287 {
1288 smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
d008864d 1289 if (newdev) {
2127e193 1290 // NOTE: 'this' is now owned by '*newdev'
d008864d
GI
1291 if(!strcmp("mfi",m_camdev->sim_name)) {
1292 newdev->close();
1293 newdev->set_err(ENOSYS, "SATA device detected,\n"
1294 "MegaRAID SAT layer is reportedly buggy, use '-d sat' to try anyhow");
1295 }
2127e193 1296 return newdev;
d008864d 1297 }
2127e193 1298 }
2127e193
GI
1299
1300 // Nothing special found
1301 return this;
1302}
1303
1304
1305/////////////////////////////////////////////////////////////////////////////
1306/// Implement platform interface with old functions.
1307
1308class freebsd_smart_interface
1309: public /*implements*/ smart_interface
1310{
1311public:
54965743 1312 virtual std::string get_os_version_str();
2127e193 1313
54965743 1314 virtual std::string get_app_examples(const char * appname);
2127e193
GI
1315
1316 virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
1317 const char * pattern = 0);
1318
1319protected:
1320 virtual ata_device * get_ata_device(const char * name, const char * type);
1321
eb07ddf2
GI
1322#if FREEBSDVER > 800100
1323 virtual ata_device * get_atacam_device(const char * name, const char * type);
1324#endif
1325
2127e193
GI
1326 virtual scsi_device * get_scsi_device(const char * name, const char * type);
1327
1328 virtual smart_device * autodetect_smart_device(const char * name);
1329
1330 virtual smart_device * get_custom_smart_device(const char * name, const char * type);
1331
54965743 1332 virtual std::string get_valid_custom_dev_types_str();
2127e193
GI
1333};
1334
1335
1336//////////////////////////////////////////////////////////////////////
54965743
GI
1337
1338std::string freebsd_smart_interface::get_os_version_str()
2127e193 1339{
54965743
GI
1340 struct utsname osname;
1341 uname(&osname);
1342 return strprintf("%s %s %s", osname.sysname, osname.release, osname.machine);
2127e193
GI
1343}
1344
54965743 1345std::string freebsd_smart_interface::get_app_examples(const char * appname)
2127e193
GI
1346{
1347 if (!strcmp(appname, "smartctl"))
1348 return smartctl_examples;
54965743 1349 return "";
2127e193
GI
1350}
1351
1352ata_device * freebsd_smart_interface::get_ata_device(const char * name, const char * type)
1353{
1354 return new freebsd_ata_device(this, name, type);
1355}
1356
eb07ddf2
GI
1357#if FREEBSDVER > 800100
1358ata_device * freebsd_smart_interface::get_atacam_device(const char * name, const char * type)
2127e193 1359{
eb07ddf2 1360 return new freebsd_atacam_device(this, name, type);
2127e193 1361}
eb07ddf2 1362#endif
832b75ed 1363
eb07ddf2
GI
1364scsi_device * freebsd_smart_interface::get_scsi_device(const char * name, const char * type)
1365{
1366 return new freebsd_scsi_device(this, name, type);
832b75ed
GG
1367}
1368
54965743
GI
1369// we are using CAM subsystem XPT enumerator to found all CAM (scsi/usb/ada/...)
1370// devices on system despite of it's names
2127e193
GI
1371//
1372// If any errors occur, leave errno set as it was returned by the
1373// system call, and return <0.
1374//
eb07ddf2
GI
1375// arguments:
1376// names: resulting array
1377// show_all - export duplicate device name or not
1378//
2127e193
GI
1379// Return values:
1380// -1: error
1381// >=0: number of discovered devices
832b75ed 1382
cfbba5b9
GI
1383bool get_dev_names_cam(std::vector<std::string> & names, bool show_all)
1384{
1385 int fd;
2127e193
GI
1386 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
1387 if (errno == ENOENT) /* There are no CAM device on this computer */
1388 return 0;
cfbba5b9 1389 int serrno = errno;
2127e193 1390 pout("%s control device couldn't opened: %s\n", XPT_DEVICE, strerror(errno));
cfbba5b9
GI
1391 errno = serrno;
1392 return false;
832b75ed 1393 }
2127e193 1394
cfbba5b9 1395 union ccb ccb;
2127e193
GI
1396 bzero(&ccb, sizeof(union ccb));
1397
1398 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
1399 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1400 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1401
1402 ccb.ccb_h.func_code = XPT_DEV_MATCH;
cfbba5b9 1403 int bufsize = sizeof(struct dev_match_result) * MAX_NUM_DEV;
2127e193 1404 ccb.cdm.match_buf_len = bufsize;
cfbba5b9 1405 // TODO: Use local buffer instead of malloc() if possible
2127e193 1406 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
a7e8ffec
GI
1407 bzero(ccb.cdm.matches,bufsize); // clear ccb.cdm.matches structure
1408
2127e193 1409 if (ccb.cdm.matches == NULL) {
cfbba5b9
GI
1410 close(fd);
1411 throw std::bad_alloc();
2127e193
GI
1412 }
1413 ccb.cdm.num_matches = 0;
2127e193
GI
1414 ccb.cdm.num_patterns = 0;
1415 ccb.cdm.pattern_buf_len = 0;
1416
1417 /*
1418 * We do the ioctl multiple times if necessary, in case there are
1419 * more than MAX_NUM_DEV nodes in the EDT.
1420 */
cfbba5b9
GI
1421 int skip_device = 0, skip_bus = 0, changed = 0; // TODO: bool
1422 std::string devname;
2127e193
GI
1423 do {
1424 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
cfbba5b9 1425 int serrno = errno;
2127e193 1426 pout("error sending CAMIOCOMMAND ioctl: %s\n", strerror(errno));
cfbba5b9
GI
1427 free(ccb.cdm.matches);
1428 close(fd);
1429 errno = serrno;
1430 return false;
832b75ed 1431 }
2127e193
GI
1432
1433 if ((ccb.ccb_h.status != CAM_REQ_CMP)
54965743
GI
1434 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
1435 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
2127e193 1436 pout("got CAM error %#x, CDM error %d\n", ccb.ccb_h.status, ccb.cdm.status);
cfbba5b9
GI
1437 free(ccb.cdm.matches);
1438 close(fd);
1439 errno = ENXIO;
1440 return false;
832b75ed 1441 }
2127e193 1442
cfbba5b9 1443 for (unsigned i = 0; i < ccb.cdm.num_matches; i++) {
2127e193
GI
1444 struct bus_match_result *bus_result;
1445 struct device_match_result *dev_result;
1446 struct periph_match_result *periph_result;
1447
1448 if (ccb.cdm.matches[i].type == DEV_MATCH_BUS) {
1449 bus_result = &ccb.cdm.matches[i].result.bus_result;
1450
d008864d 1451 if (strcmp(bus_result->dev_name,"xpt") == 0) /* skip XPT bus at all */
54965743 1452 skip_bus = 1;
2127e193
GI
1453 else
1454 skip_bus = 0;
1455 changed = 1;
1456 } else if (ccb.cdm.matches[i].type == DEV_MATCH_DEVICE) {
1457 dev_result = &ccb.cdm.matches[i].result.device_result;
1458
1459 if (dev_result->flags & DEV_RESULT_UNCONFIGURED || skip_bus == 1)
1460 skip_device = 1;
1461 else
1462 skip_device = 0;
eb07ddf2 1463
54965743
GI
1464 // /* Shall we skip non T_DIRECT devices ? */
1465 // if (dev_result->inq_data.device != T_DIRECT)
1466 // skip_device = 1;
2127e193 1467 changed = 1;
eb07ddf2
GI
1468 } else if (ccb.cdm.matches[i].type == DEV_MATCH_PERIPH &&
1469 (skip_device == 0 || show_all)) {
2127e193 1470 /* One device may be populated as many peripherals (pass0 & da0 for example).
ee38a438 1471 * We are searching for best name
2127e193
GI
1472 */
1473 periph_result = &ccb.cdm.matches[i].result.periph_result;
ee38a438
GI
1474 /* Prefer non-"pass" names */
1475 if (devname.empty() || strncmp(periph_result->periph_name, "pass", 4) != 0) {
1476 devname = strprintf("%s%s%d", _PATH_DEV, periph_result->periph_name, periph_result->unit_number);
1477 }
2127e193
GI
1478 changed = 0;
1479 };
cfbba5b9
GI
1480 if ((changed == 1 || show_all) && !devname.empty()) {
1481 names.push_back(devname);
1482 devname.erase();
2127e193
GI
1483 changed = 0;
1484 };
1485 }
1486
cfbba5b9 1487 } while ((ccb.ccb_h.status == CAM_REQ_CMP) && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
2127e193 1488
cfbba5b9
GI
1489 if (!devname.empty())
1490 names.push_back(devname);
2127e193 1491
2127e193 1492 free(ccb.cdm.matches);
cfbba5b9
GI
1493 close(fd);
1494 return true;
832b75ed 1495}
832b75ed 1496
2127e193
GI
1497// we are using ATA subsystem enumerator to found all ATA devices on system
1498// despite of it's names
1499//
1500// If any errors occur, leave errno set as it was returned by the
1501// system call, and return <0.
832b75ed 1502
2127e193
GI
1503// Return values:
1504// -1: error
1505// >=0: number of discovered devices
1506int get_dev_names_ata(char*** names) {
1507 struct ata_ioc_devices devices;
1508 int fd=-1,maxchannel,serrno=-1,n=0;
1509 char **mp = NULL;
1510
1511 *names=NULL;
1512
1513 if ((fd = open(ATA_DEVICE, O_RDWR)) < 0) {
1514 if (errno == ENOENT) /* There are no ATA device on this computer */
1515 return 0;
1516 serrno = errno;
1517 pout("%s control device can't be opened: %s\n", ATA_DEVICE, strerror(errno));
1518 n = -1;
1519 goto end;
1520 };
54965743 1521
2127e193
GI
1522 if (ioctl(fd, IOCATAGMAXCHANNEL, &maxchannel) < 0) {
1523 serrno = errno;
1524 pout("ioctl(IOCATAGMAXCHANNEL) on /dev/ata failed: %s\n", strerror(errno));
1525 n = -1;
1526 goto end;
1527 };
1528
1529 // allocate space for up to MAX_NUM_DEV number of ATA devices
1530 mp = (char **)calloc(MAX_NUM_DEV, sizeof(char*));
1531 if (mp == NULL) {
1532 serrno=errno;
1533 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__);
1534 n = -1;
1535 goto end;
1536 };
1537
1538 for (devices.channel = 0; devices.channel < maxchannel && n < MAX_NUM_DEV; devices.channel++) {
1539 int j;
54965743 1540
2127e193
GI
1541 if (ioctl(fd, IOCATADEVICES, &devices) < 0) {
1542 if (errno == ENXIO)
1543 continue; /* such channel not exist */
1544 pout("ioctl(IOCATADEVICES) on %s channel %d failed: %s\n", ATA_DEVICE, devices.channel, strerror(errno));
1545 n = -1;
1546 goto end;
1547 };
1548 for (j=0;j<=1 && n<MAX_NUM_DEV;j++) {
1549 if (devices.name[j][0] != '\0') {
1550 asprintf(mp+n, "%s%s", _PATH_DEV, devices.name[j]);
1551 if (mp[n] == NULL) {
1552 pout("Out of memory constructing scan ATA device list (on line %d)\n", __LINE__);
1553 n = -1;
1554 goto end;
1555 };
1556 bytes+=1+strlen(mp[n]);
1557 n++;
1558 };
1559 };
1560 };
1561 mp = (char **)reallocf(mp,n*(sizeof (char*))); // shrink to correct size
f4ebf3d1
GI
1562 if (mp == NULL && n > 0 ) { // reallocf never fail for size=0, but may return NULL
1563 serrno=errno;
1564 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__);
1565 n = -1;
1566 goto end;
1567 };
2127e193 1568 bytes += (n)*(sizeof(char*)); // and set allocated byte count
54965743 1569
2127e193
GI
1570end:
1571 if (fd>=0)
1572 close(fd);
1573 if (n <= 0) {
1574 free(mp);
1575 mp = NULL;
832b75ed 1576 }
832b75ed 1577
2127e193 1578 *names=mp;
832b75ed 1579
2127e193
GI
1580 if (serrno>-1)
1581 errno=serrno;
1582 return n;
1583}
832b75ed 1584
2127e193
GI
1585
1586
1587bool freebsd_smart_interface::scan_smart_devices(smart_device_list & devlist,
1588 const char * type, const char * pattern /*= 0*/)
1589{
1590 if (pattern) {
1591 set_err(EINVAL, "DEVICESCAN with pattern not implemented yet");
1592 return false;
832b75ed
GG
1593 }
1594
2127e193
GI
1595 // Make namelists
1596 char * * atanames = 0; int numata = 0;
1597 if (!type || !strcmp(type, "ata")) {
1598 numata = get_dev_names_ata(&atanames);
1599 if (numata < 0) {
1600 set_err(ENOMEM);
1601 return false;
832b75ed 1602 }
2127e193
GI
1603 }
1604
cfbba5b9 1605 std::vector<std::string> scsinames;
eb07ddf2 1606 if (!type || !strcmp(type, "scsi")) { // do not export duplicated names
cfbba5b9
GI
1607 if (!get_dev_names_cam(scsinames, false)) {
1608 set_err(errno);
2127e193 1609 return false;
832b75ed 1610 }
832b75ed
GG
1611 }
1612
2127e193
GI
1613 // Add to devlist
1614 int i;
1615 if (type==NULL)
1616 type="";
1617 for (i = 0; i < numata; i++) {
1618 ata_device * atadev = get_ata_device(atanames[i], type);
1619 if (atadev)
bed94269 1620 devlist.push_back(atadev);
a7e8ffec 1621 free(atanames[i]);
2127e193 1622 }
a7e8ffec 1623 if(numata) free(atanames);
832b75ed 1624
cfbba5b9 1625 for (i = 0; i < (int)scsinames.size(); i++) {
54965743 1626 if(!*type) { // try USB autodetection if no type specified
cfbba5b9 1627 smart_device * smartdev = autodetect_smart_device(scsinames[i].c_str());
54965743 1628 if(smartdev)
bed94269 1629 devlist.push_back(smartdev);
54965743
GI
1630 }
1631 else {
cfbba5b9 1632 scsi_device * scsidev = get_scsi_device(scsinames[i].c_str(), type);
54965743 1633 if (scsidev)
bed94269 1634 devlist.push_back(scsidev);
54965743 1635 }
832b75ed 1636 }
2127e193 1637 return true;
832b75ed
GG
1638}
1639
2127e193 1640
54965743 1641#if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8
2127e193 1642static char done[USB_MAX_DEVICES];
2127e193
GI
1643
1644static int usbdevinfo(int f, int a, int rec, int busno, unsigned short & vendor_id,
54965743
GI
1645 unsigned short & product_id, unsigned short & version)
1646{
832b75ed 1647
54965743
GI
1648 struct usb_device_info di;
1649 int e, p, i;
1650 char devname[256];
832b75ed 1651
54965743
GI
1652 snprintf(devname, sizeof(devname),"umass%d",busno);
1653
1654 di.udi_addr = a;
1655 e = ioctl(f, USB_DEVICEINFO, &di);
1656 if (e) {
1657 if (errno != ENXIO)
1658 printf("addr %d: I/O error\n", a);
1659 return 0;
1660 }
1661 done[a] = 1;
1662
1663 // list devices
1664 for (i = 0; i < USB_MAX_DEVNAMES; i++) {
1665 if (di.udi_devnames[i][0]) {
1666 if(strcmp(di.udi_devnames[i],devname)==0) {
1667 // device found!
1668 vendor_id = di.udi_vendorNo;
1669 product_id = di.udi_productNo;
1670 version = di.udi_releaseNo;
1671 return 1;
1672 // FIXME
1673 }
1674 }
1675 }
1676 if (!rec)
1677 return 0;
1678 for (p = 0; p < di.udi_nports; p++) {
1679 int s = di.udi_ports[p];
1680 if (s >= USB_MAX_DEVICES) {
1681 continue;
1682 }
1683 if (s == 0)
1684 printf("addr 0 should never happen!\n");
1685 else {
1686 if(usbdevinfo(f, s, 1, busno, vendor_id, product_id, version)) return 1;
1687 }
1688 }
1689 return 0;
1690}
1691#endif
832b75ed 1692
832b75ed 1693
2127e193 1694static int usbdevlist(int busno,unsigned short & vendor_id,
54965743 1695 unsigned short & product_id, unsigned short & version)
2127e193 1696{
54965743
GI
1697#if (FREEBSDVER >= 800000) // libusb2 interface
1698 struct libusb20_device *pdev = NULL;
1699 struct libusb20_backend *pbe;
1700 uint32_t matches = 0;
1701 char buf[128]; // do not change!
1702 char devname[128];
1703 uint8_t n;
1704 struct LIBUSB20_DEVICE_DESC_DECODED *pdesc;
1705
1706 pbe = libusb20_be_alloc_default();
1707
1708 while ((pdev = libusb20_be_device_foreach(pbe, pdev))) {
1709 matches++;
1710
1711 if (libusb20_dev_open(pdev, 0)) {
1712 warnx("libusb20_dev_open: could not open device");
1713 return 0;
2127e193 1714 }
54965743
GI
1715
1716 pdesc=libusb20_dev_get_device_desc(pdev);
1717
1718 snprintf(devname, sizeof(devname),"umass%d:",busno);
1719 for (n = 0; n != 255; n++) {
1720 if (libusb20_dev_get_iface_desc(pdev, n, buf, sizeof(buf)))
1721 break;
1722 if (buf[0] == 0)
1723 continue;
1724 if(strncmp(buf,devname,strlen(devname))==0){
1725 // found!
1726 vendor_id = pdesc->idVendor;
1727 product_id = pdesc->idProduct;
1728 version = pdesc->bcdDevice;
1729 libusb20_dev_close(pdev);
1730 libusb20_be_free(pbe);
1731 return 1;
1732 }
1733 }
1734
1735 libusb20_dev_close(pdev);
1736 }
1737
1738 if (matches == 0) {
1739 printf("No device match or lack of permissions.\n");
1740 }
1741
1742 libusb20_be_free(pbe);
1743
1744 return false;
1745#else // freebsd < 8.0 USB stack, ioctl interface
1746
1747 int i, f, a, rc;
1748 char buf[50];
1749 int ncont;
1750
1751 for (ncont = 0, i = 0; i < 10; i++) {
1752 snprintf(buf, sizeof(buf), "%s%d", USBDEV, i);
1753 f = open(buf, O_RDONLY);
1754 if (f >= 0) {
1755 memset(done, 0, sizeof done);
1756 for (a = 1; a < USB_MAX_DEVICES; a++) {
1757 if (!done[a]) {
1758 rc = usbdevinfo(f, a, 1, busno,vendor_id, product_id, version);
1759 if(rc) return 1;
1760 }
1761
1762 }
1763 close(f);
1764 } else {
1765 if (errno == ENOENT || errno == ENXIO)
1766 continue;
1767 warn("%s", buf);
1768 }
1769 ncont++;
1770 }
1771 return 0;
1772#endif
2127e193
GI
1773}
1774
2127e193
GI
1775smart_device * freebsd_smart_interface::autodetect_smart_device(const char * name)
1776{
2127e193 1777 unsigned short vendor_id = 0, product_id = 0, version = 0;
eb07ddf2
GI
1778 struct cam_device *cam_dev;
1779 union ccb ccb;
1780 int bus=-1;
a7e8ffec 1781 int i,c;
eb07ddf2 1782 int len;
d008864d 1783 const char * test_name = name;
54965743 1784
eb07ddf2
GI
1785 // if dev_name null, or string length zero
1786 if (!name || !(len = strlen(name)))
d008864d
GI
1787 return 0;
1788
1789 // Dereference symlinks
1790 struct stat st;
1791 std::string pathbuf;
1792 if (!lstat(name, &st) && S_ISLNK(st.st_mode)) {
1793 char * p = realpath(name, (char *)0);
1794 if (p) {
1795 pathbuf = p;
1796 free(p);
1797 test_name = pathbuf.c_str();
1798 }
1799 }
eb07ddf2
GI
1800
1801 // check ATA bus
1802 char * * atanames = 0; int numata = 0;
1803 numata = get_dev_names_ata(&atanames);
1804 if (numata > 0) {
1805 // check ATA/ATAPI devices
1806 for (i = 0; i < numata; i++) {
d008864d 1807 if(!strcmp(atanames[i],test_name)) {
a7e8ffec
GI
1808 for (c = i; c < numata; c++) free(atanames[c]);
1809 free(atanames);
d008864d 1810 return new freebsd_ata_device(this, test_name, "");
eb07ddf2 1811 }
a7e8ffec 1812 else free(atanames[i]);
832b75ed 1813 }
a7e8ffec 1814 if(numata) free(atanames);
832b75ed 1815 }
eb07ddf2
GI
1816 else {
1817 if (numata < 0)
1818 pout("Unable to get ATA device list\n");
1819 }
1820
1821 // check CAM
cfbba5b9
GI
1822 std::vector<std::string> scsinames;
1823 if (!get_dev_names_cam(scsinames, true))
1824 pout("Unable to get CAM device list\n");
1825 else if (!scsinames.empty()) {
eb07ddf2 1826 // check all devices on CAM bus
cfbba5b9 1827 for (i = 0; i < (int)scsinames.size(); i++) {
d008864d 1828 if(strcmp(scsinames[i].c_str(), test_name)==0)
eb07ddf2 1829 { // our disk device is CAM
d008864d 1830 if ((cam_dev = cam_open_device(test_name, O_RDWR)) == NULL) {
eb07ddf2
GI
1831 // open failure
1832 set_err(errno);
d008864d 1833 return 0;
eb07ddf2 1834 }
eb07ddf2
GI
1835 // zero the payload
1836 bzero(&(&ccb.ccb_h)[1], PATHINQ_SETTINGS_SIZE);
1837 ccb.ccb_h.func_code = XPT_PATH_INQ; // send PATH_INQ to the device
1838 if (ioctl(cam_dev->fd, CAMIOCOMMAND, &ccb) == -1) {
1839 warn("Get Transfer Settings CCB failed\n"
1840 "%s", strerror(errno));
1841 cam_close_device(cam_dev);
1842 return 0;
1843 }
1844 // now check if we are working with USB device, see umass.c
1845 if(strcmp(ccb.cpi.dev_name,"umass-sim") == 0) { // USB device found
1846 usbdevlist(bus,vendor_id, product_id, version);
1847 int bus=ccb.cpi.unit_number; // unit_number will match umass number
1848 cam_close_device(cam_dev);
1849 if(usbdevlist(bus,vendor_id, product_id, version)){
1850 const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id, version);
f4ebf3d1 1851 if (usbtype)
d008864d 1852 return get_sat_device(usbtype, new freebsd_scsi_device(this, test_name, ""));
eb07ddf2 1853 }
d008864d 1854 return 0;
eb07ddf2
GI
1855 }
1856#if FREEBSDVER > 800100
1857 // check if we have ATA device connected to CAM (ada)
1858 if(ccb.cpi.protocol == PROTO_ATA){
1859 cam_close_device(cam_dev);
d008864d 1860 return new freebsd_atacam_device(this, test_name, "");
eb07ddf2
GI
1861 }
1862#endif
1863 // close cam device, we don`t need it anymore
1864 cam_close_device(cam_dev);
1865 // handle as usual scsi
d008864d 1866 return new freebsd_scsi_device(this, test_name, "");
eb07ddf2
GI
1867 }
1868 }
eb07ddf2 1869 }
d008864d
GI
1870 // device is LSI raid supported by mfi driver
1871 if(!strncmp("/dev/mfid", test_name, strlen("/dev/mfid")))
1872 set_err(EINVAL, "To monitor disks on LSI RAID load mfip.ko module and run 'smartctl -a /dev/passX' to show SMART information");
eb07ddf2 1873 // device type unknown
2127e193
GI
1874 return 0;
1875}
1876
1877
1878smart_device * freebsd_smart_interface::get_custom_smart_device(const char * name, const char * type)
1879{
1880 // 3Ware ?
eb07ddf2
GI
1881 static const char * fbsd_dev_twe_ctrl = "/dev/twe";
1882 static const char * fbsd_dev_twa_ctrl = "/dev/twa";
ee38a438 1883 static const char * fbsd_dev_tws_ctrl = "/dev/tws";
eb07ddf2
GI
1884 int disknum = -1, n1 = -1, n2 = -1, contr = -1;
1885
2127e193
GI
1886 if (sscanf(type, "3ware,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
1887 if (n2 != (int)strlen(type)) {
1888 set_err(EINVAL, "Option -d 3ware,N requires N to be a non-negative integer");
1889 return 0;
1890 }
1891 if (!(0 <= disknum && disknum <= 127)) {
1892 set_err(EINVAL, "Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum);
1893 return 0;
1894 }
eb07ddf2
GI
1895
1896 // guess 3ware device type based on device name
ee38a438
GI
1897 if (str_starts_with(name, fbsd_dev_twa_ctrl) ||
1898 str_starts_with(name, fbsd_dev_tws_ctrl) ) {
eb07ddf2
GI
1899 contr=CONTROLLER_3WARE_9000_CHAR;
1900 }
1901 if (!strncmp(fbsd_dev_twe_ctrl, name, strlen(fbsd_dev_twe_ctrl))){
1902 contr=CONTROLLER_3WARE_678K_CHAR;
1903 }
1904
1905 if(contr == -1){
ee38a438
GI
1906 set_err(EINVAL, "3ware controller type unknown, use %sX, %sX or %sX devices",
1907 fbsd_dev_twe_ctrl, fbsd_dev_twa_ctrl, fbsd_dev_tws_ctrl);
eb07ddf2
GI
1908 return 0;
1909 }
54965743 1910 return new freebsd_escalade_device(this, name, contr, disknum);
ee38a438 1911 }
2127e193
GI
1912
1913 // Highpoint ?
1914 int controller = -1, channel = -1; disknum = 1;
1915 n1 = n2 = -1; int n3 = -1;
1916 if (sscanf(type, "hpt,%n%d/%d%n/%d%n", &n1, &controller, &channel, &n2, &disknum, &n3) >= 2 || n1 == 4) {
1917 int len = strlen(type);
1918 if (!(n2 == len || n3 == len)) {
1919 set_err(EINVAL, "Option '-d hpt,L/M/N' supports 2-3 items");
1920 return 0;
1921 }
1922 if (!(1 <= controller && controller <= 8)) {
1923 set_err(EINVAL, "Option '-d hpt,L/M/N' invalid controller id L supplied");
1924 return 0;
1925 }
d008864d 1926 if (!(1 <= channel && channel <= 16)) {
2127e193
GI
1927 set_err(EINVAL, "Option '-d hpt,L/M/N' invalid channel number M supplied");
1928 return 0;
1929 }
1930 if (!(1 <= disknum && disknum <= 15)) {
1931 set_err(EINVAL, "Option '-d hpt,L/M/N' invalid pmport number N supplied");
1932 return 0;
1933 }
1934 return new freebsd_highpoint_device(this, name, controller, channel, disknum);
832b75ed
GG
1935 }
1936
2127e193
GI
1937 // CCISS ?
1938 disknum = n1 = n2 = -1;
1939 if (sscanf(type, "cciss,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
1940 if (n2 != (int)strlen(type)) {
1941 set_err(EINVAL, "Option -d cciss,N requires N to be a non-negative integer");
1942 return 0;
1943 }
e9583e0c
GI
1944 if (!(0 <= disknum && disknum <= 127)) {
1945 set_err(EINVAL, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum);
2127e193
GI
1946 return 0;
1947 }
ee38a438 1948 return get_sat_device("sat,auto", new freebsd_cciss_device(this, name, disknum));
832b75ed 1949 }
eb07ddf2
GI
1950#if FREEBSDVER > 800100
1951 // adaX devices ?
1952 if(!strcmp(type,"atacam"))
1953 return new freebsd_atacam_device(this, name, "");
1954#endif
d008864d
GI
1955 // Areca?
1956 disknum = n1 = n2 = -1;
f4e463df
GI
1957 int encnum = 1;
1958 if (sscanf(type, "areca,%n%d/%d%n", &n1, &disknum, &encnum, &n2) >= 1 || n1 == 6) {
1959 if (!(1 <= disknum && disknum <= 128)) {
1960 set_err(EINVAL, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum);
d008864d
GI
1961 return 0;
1962 }
f4e463df
GI
1963 if (!(1 <= encnum && encnum <= 8)) {
1964 set_err(EINVAL, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum);
d008864d
GI
1965 return 0;
1966 }
ee38a438 1967 return new freebsd_areca_ata_device(this, name, disknum, encnum);
d008864d 1968 }
832b75ed 1969
2127e193 1970 return 0;
832b75ed
GG
1971}
1972
54965743 1973std::string freebsd_smart_interface::get_valid_custom_dev_types_str()
2127e193 1974{
f4e463df 1975 return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E"
eb07ddf2
GI
1976#if FREEBSDVER > 800100
1977 ", atacam"
1978#endif
1979 ;
2127e193
GI
1980}
1981
2127e193
GI
1982} // namespace
1983
2127e193
GI
1984/////////////////////////////////////////////////////////////////////////////
1985/// Initialize platform interface and register with smi()
1986
1987void smart_interface::init()
1988{
1989 static os_freebsd::freebsd_smart_interface the_interface;
1990 smart_interface::set(&the_interface);
832b75ed 1991}