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