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