Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 25 Apr 2006 18:48:56 GMT
From:      dawnshade <h-k@mail.ru>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   ports/96325: UPDATE sysutils/smartmontools to 5.36
Message-ID:  <200604251848.k3PImuZr095435@www.freebsd.org>
Resent-Message-ID: <200604251850.k3PIoGHu073821@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         96325
>Category:       ports
>Synopsis:       UPDATE sysutils/smartmontools to 5.36
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          update
>Submitter-Id:   current-users
>Arrival-Date:   Tue Apr 25 18:50:15 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     dawnshade
>Release:        6.1-PRE
>Organization:
-
>Environment:
FreeBSD mail.host.tld 6.1-PRERELEASE FreeBSD 6.1-PRERELEASE #0: Fri Feb 10 17:00:36 MSK 2006     root@mail.host.tld:/usr/src/sys/i386/compile/mail_kern_4  i386
>Description:
Update sysutils/smartmontools to 5.36
Patch is below. All files/patch-* removed because already integrated in main tarball by author.
>How-To-Repeat:
-
>Fix:
diff -ruN smartmontools smartmontools.old
diff -ruN smartmontools/Makefile smartmontools.old/Makefile
--- smartmontools/Makefile      Tue Apr 25 22:27:16 2006
+++ smartmontools.old/Makefile  Tue Apr 25 22:26:25 2006
@@ -6,7 +6,8 @@
 #
 
 PORTNAME=      smartmontools
-PORTVERSION=   5.36
+PORTVERSION=   5.33
+PORTREVISION=  5
 CATEGORIES=    sysutils
 MASTER_SITES=  ${MASTER_SITE_SOURCEFORGE}
 MASTER_SITE_SUBDIR=    ${PORTNAME}
diff -ruN smartmontools/distinfo smartmontools.old/distinfo
--- smartmontools/distinfo      Tue Apr 25 22:30:47 2006
+++ smartmontools.old/distinfo  Tue Apr 25 22:26:25 2006
@@ -1,3 +1,3 @@
-MD5 (smartmontools-5.36.tar.gz) = 2e424f2d35efa38a29ebca419c1dbe3c
-SHA256 (smartmontools-5.36.tar.gz) = f2032adf22f8d17aad7f3dbed0a9361c25e273d3ca6abb996c84159afd624bf4
-SIZE (smartmontools-5.36.tar.gz) = 540786
+MD5 (smartmontools-5.33.tar.gz) = 53f6861a916169a88a9edb1848e27dd0
+SHA256 (smartmontools-5.33.tar.gz) = 2fdde1b4e610cd6e004db8f98ac1100fcbea03b8f11e236de536ce22bc6c620d
+SIZE (smartmontools-5.33.tar.gz) = 509826
diff -ruN smartmontools/files/patch-config.h.in smartmontools.old/files/patch-config.h.in
--- smartmontools/files/patch-config.h.in       Thu Jan  1 03:00:00 1970
+++ smartmontools.old/files/patch-config.h.in   Tue Apr 25 22:26:25 2006
@@ -0,0 +1,12 @@
+--- config.h.in.orig   Thu Aug  4 15:16:22 2005
++++ config.h.in        Thu Aug  4 15:19:21 2005
+@@ -66,6 +66,9 @@
+ /* Define to 1 if you have the <sys/twereg.h> header file. */
+ #undef HAVE_SYS_TWEREG_H
+ 
++/* Define to 1 if you have the <sys/tw_osl_ioctl.h> header file. */
++#undef HAVE_SYS_TW_OSL_IOCTL_H
++
+ /* Define to 1 if you have the <sys/types.h> header file. */
+ #undef HAVE_SYS_TYPES_H
+ 
diff -ruN smartmontools/files/patch-configure.in smartmontools.old/files/patch-configure.in
--- smartmontools/files/patch-configure.in      Thu Jan  1 03:00:00 1970
+++ smartmontools.old/files/patch-configure.in  Tue Apr 25 22:26:25 2006
@@ -0,0 +1,11 @@
+--- configure.in.orig  Thu Aug  4 15:16:15 2005
++++ configure.in       Thu Aug  4 15:18:50 2005
+@@ -56,6 +56,8 @@
+ dnl Check for FreeBSD twe include files...currently missing on 5.2, but should be there
+ AC_CHECK_HEADERS([sys/tweio.h])
+ AC_CHECK_HEADERS([sys/twereg.h])
++dnl Check for FreeBSD twa include files...
++AC_CHECK_HEADERS([sys/tw_osl_ioctl.h])
+ 
+ dnl Checks for typedefs, structures, and compiler characteristics.
+ 
diff -ruN smartmontools/files/patch-os_freebsd.c smartmontools.old/files/patch-os_freebsd.c
--- smartmontools/files/patch-os_freebsd.c      Thu Jan  1 03:00:00 1970
+++ smartmontools.old/files/patch-os_freebsd.c  Tue Apr 25 22:26:25 2006
@@ -0,0 +1,641 @@
+--- os_freebsd.c.orig  Sun Oct  9 13:00:56 2005
++++ os_freebsd.c       Sun Oct  9 13:00:46 2005
+@@ -18,6 +18,7 @@
+ #include <stdio.h>
+ #include <sys/types.h>
+ #include <dirent.h>
++#include <fcntl.h>
+ #include <err.h>
+ #include <camlib.h>
+ #include <cam/scsi/scsi_message.h>
+@@ -109,7 +110,11 @@
+   }
+ 
+   if (parse_ok == CONTROLLER_ATA) {
++#ifdef IOCATAREQUEST
++    if ((fdchan->device = open(dev,O_RDONLY))<0) {
++#else
+     if ((fdchan->atacommand = open("/dev/ata",O_RDWR))<0) {
++#endif
+       int myerror = errno;      //preserve across free call
+       free (fdchan);
+       errno = myerror;
+@@ -120,7 +125,26 @@
+   if (parse_ok == CONTROLLER_3WARE_678K_CHAR) {
+     char buf[512];
+     sprintf(buf,"/dev/twe%d",fdchan->device);
++#ifdef IOCATAREQUEST
++    if ((fdchan->device = open(buf,O_RDWR))<0) {
++#else
+     if ((fdchan->atacommand = open(buf,O_RDWR))<0) {
++#endif
++      int myerror = errno; // preserver across free call
++      free(fdchan);
++      errno=myerror;
++      return -1;
++    }
++  }
++
++  if (parse_ok == CONTROLLER_3WARE_9000_CHAR) {
++    char buf[512];
++    sprintf(buf,"/dev/twa%d",fdchan->device);
++#ifdef IOCATAREQUEST
++    if ((fdchan->device = open(buf,O_RDWR))<0) {
++#else
++    if ((fdchan->atacommand = open(buf,O_RDWR))<0) {
++#endif
+       int myerror = errno; // preserver across free call
+       free(fdchan);
+       errno=myerror;
+@@ -167,8 +191,13 @@
+     free(fdchan->devname);
+   
+   // close device, if open
++#ifdef IOCATAREQUEST
++  if (fdchan->device)
++    failed=close(fdchan->device);
++#else
+   if (fdchan->atacommand)
+     failed=close(fdchan->atacommand);
++#endif
+ 
+   if (fdchan->scsicontrol)
+     failed=close(fdchan->scsicontrol);
+@@ -221,7 +250,7 @@
+ }
+ 
+ int ata_command_interface(int fd, smart_command_set command, int select, char *data) {
+-#ifndef ATAREQUEST
++#if !defined(ATAREQUEST) && !defined(IOCATAREQUEST)
+   // sorry, but without ATAng, we can't do anything here
+   printwarning(BAD_KERNEL,NULL);
+   errno = ENOSYS;
+@@ -229,7 +258,11 @@
+ #else
+   struct freebsd_dev_channel* con;
+   int retval, copydata=0;
++#ifdef IOCATAREQUEST
++  struct ata_ioc_request request;
++#else
+   struct ata_cmd iocmd;
++#endif
+   unsigned char buff[512];
+ 
+   // check that "file descriptor" is valid
+@@ -238,89 +271,97 @@
+ 
+   bzero(buff,512);
+ 
++#ifdef IOCATAREQUEST
++  bzero(&request,sizeof(struct ata_ioc_request));
++#else
+   bzero(&iocmd,sizeof(struct ata_cmd));
++#endif
+   bzero(buff,512);
++
++#ifndef IOCATAREQUEST
+   iocmd.cmd=ATAREQUEST;
+   iocmd.channel=con->channel;
+   iocmd.device=con->device;
++#define request iocmd.u.request
++#endif
+ 
+-  iocmd.u.request.u.ata.command=ATA_SMART_CMD;
+-  iocmd.u.request.timeout=600;
++  request.u.ata.command=ATA_SMART_CMD;
++  request.timeout=600;
+   switch (command){
+   case READ_VALUES:
+-    iocmd.u.request.u.ata.feature=ATA_SMART_READ_VALUES;
+-    iocmd.u.request.u.ata.lba=0xc24f<<8;
+-    iocmd.u.request.flags=ATA_CMD_READ;
+-    iocmd.u.request.data=buff;
+-    iocmd.u.request.count=512;
++    request.u.ata.feature=ATA_SMART_READ_VALUES;
++    request.u.ata.lba=0xc24f<<8;
++    request.flags=ATA_CMD_READ;
++    request.data=buff;
++    request.count=512;
+     copydata=1;
+     break;
+   case READ_THRESHOLDS:
+-    iocmd.u.request.u.ata.feature=ATA_SMART_READ_THRESHOLDS;
+-    iocmd.u.request.u.ata.count=1;
+-    iocmd.u.request.u.ata.lba=1|(0xc24f<<8);
+-    iocmd.u.request.flags=ATA_CMD_READ;
+-    iocmd.u.request.data=buff;
+-    iocmd.u.request.count=512;
++    request.u.ata.feature=ATA_SMART_READ_THRESHOLDS;
++    request.u.ata.count=1;
++    request.u.ata.lba=1|(0xc24f<<8);
++    request.flags=ATA_CMD_READ;
++    request.data=buff;
++    request.count=512;
+     copydata=1;
+     break;
+   case READ_LOG:
+-    iocmd.u.request.u.ata.feature=ATA_SMART_READ_LOG_SECTOR;
+-    iocmd.u.request.u.ata.lba=select|(0xc24f<<8);
+-    iocmd.u.request.u.ata.count=1;
+-    iocmd.u.request.flags=ATA_CMD_READ;
+-    iocmd.u.request.data=buff;
+-    iocmd.u.request.count=512;
++    request.u.ata.feature=ATA_SMART_READ_LOG_SECTOR;
++    request.u.ata.lba=select|(0xc24f<<8);
++    request.u.ata.count=1;
++    request.flags=ATA_CMD_READ;
++    request.data=buff;
++    request.count=512;
+     copydata=1;
+     break;
+   case IDENTIFY:
+-    iocmd.u.request.u.ata.command=ATA_IDENTIFY_DEVICE;
+-    iocmd.u.request.flags=ATA_CMD_READ;
+-    iocmd.u.request.data=buff;
+-    iocmd.u.request.count=512;
++    request.u.ata.command=ATA_IDENTIFY_DEVICE;
++    request.flags=ATA_CMD_READ;
++    request.data=buff;
++    request.count=512;
+     copydata=1;
+     break;
+   case PIDENTIFY:
+-    iocmd.u.request.u.ata.command=ATA_IDENTIFY_PACKET_DEVICE;
+-    iocmd.u.request.flags=ATA_CMD_READ;
+-    iocmd.u.request.data=buff;
+-    iocmd.u.request.count=512;
++    request.u.ata.command=ATA_IDENTIFY_PACKET_DEVICE;
++    request.flags=ATA_CMD_READ;
++    request.data=buff;
++    request.count=512;
+     copydata=1;
+     break;
+   case ENABLE:
+-    iocmd.u.request.u.ata.feature=ATA_SMART_ENABLE;
+-    iocmd.u.request.u.ata.lba=0xc24f<<8;
+-    iocmd.u.request.flags=ATA_CMD_CONTROL;
++    request.u.ata.feature=ATA_SMART_ENABLE;
++    request.u.ata.lba=0xc24f<<8;
++    request.flags=ATA_CMD_CONTROL;
+     break;
+   case DISABLE:
+-    iocmd.u.request.u.ata.feature=ATA_SMART_DISABLE;
+-    iocmd.u.request.u.ata.lba=0xc24f<<8;
+-    iocmd.u.request.flags=ATA_CMD_CONTROL;
++    request.u.ata.feature=ATA_SMART_DISABLE;
++    request.u.ata.lba=0xc24f<<8;
++    request.flags=ATA_CMD_CONTROL;
+     break;
+   case AUTO_OFFLINE:
+     // NOTE: According to ATAPI 4 and UP, this command is obsolete
+-    iocmd.u.request.u.ata.feature=ATA_SMART_AUTO_OFFLINE;
+-    iocmd.u.request.u.ata.lba=select|(0xc24f<<8);
+-    iocmd.u.request.flags=ATA_CMD_CONTROL;
++    request.u.ata.feature=ATA_SMART_AUTO_OFFLINE;
++    request.u.ata.lba=select|(0xc24f<<8);
++    request.flags=ATA_CMD_CONTROL;
+     break;
+   case AUTOSAVE:
+-    iocmd.u.request.u.ata.feature=ATA_SMART_AUTOSAVE;
+-    iocmd.u.request.u.ata.count=0xf1;  // to enable autosave
+-    iocmd.u.request.u.ata.lba=0xc24f<<8;
+-    iocmd.u.request.flags=ATA_CMD_CONTROL;
++    request.u.ata.feature=ATA_SMART_AUTOSAVE;
++    request.u.ata.count=0xf1;  // to enable autosave
++    request.u.ata.lba=0xc24f<<8;
++    request.flags=ATA_CMD_CONTROL;
+     break;
+   case IMMEDIATE_OFFLINE:
+-    iocmd.u.request.u.ata.feature=ATA_SMART_IMMEDIATE_OFFLINE;
+-    iocmd.u.request.u.ata.lba = select|(0xc24f<<8); // put test in sector
+-    iocmd.u.request.flags=ATA_CMD_CONTROL;
++    request.u.ata.feature=ATA_SMART_IMMEDIATE_OFFLINE;
++    request.u.ata.lba = select|(0xc24f<<8); // put test in sector
++    request.flags=ATA_CMD_CONTROL;
+     break;
+   case STATUS_CHECK: // same command, no HDIO in FreeBSD
+   case STATUS:
+     // this command only says if SMART is working.  It could be
+     // replaced with STATUS_CHECK below.
+-    iocmd.u.request.u.ata.feature=ATA_SMART_STATUS;
+-    iocmd.u.request.u.ata.lba=0xc24f<<8;
+-    iocmd.u.request.flags=ATA_CMD_CONTROL;
++    request.u.ata.feature=ATA_SMART_STATUS;
++    request.u.ata.lba=0xc24f<<8;
++    request.flags=ATA_CMD_CONTROL;
+     break;
+   default:
+     pout("Unrecognized command %d in ata_command_interface()\n"
+@@ -334,15 +375,19 @@
+     unsigned const char failed_lo=0xf4, failed_hi=0x2c;
+     unsigned char low,high;
+     
+-    if ((retval=ioctl(con->atacommand, IOCATA, &iocmd)))
++#ifdef IOCATAREQUEST
++    if ((retval=ioctl(con->device, IOCATAREQUEST, &request)) || request.error)
++#else
++    if ((retval=ioctl(con->atacommand, IOCATA, &iocmd)) || request.error)
++#endif
+       return -1;
+ 
+ #if __FreeBSD_version < 502000
+     printwarning(NO_RETURN,NULL);
+ #endif
+ 
+-    high = (iocmd.u.request.u.ata.lba >> 16) & 0xff;
+-    low = (iocmd.u.request.u.ata.lba >> 8) & 0xff;
++    high = (request.u.ata.lba >> 16) & 0xff;
++    low = (request.u.ata.lba >> 8) & 0xff;
+     
+     // Cyl low and Cyl high unchanged means "Good SMART status"
+     if (low==normal_lo && high==normal_hi)
+@@ -355,21 +400,23 @@
+     // We haven't gotten output that makes sense; print out some debugging info
+     char buf[512];
+     sprintf(buf,"CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
+-            (int)iocmd.u.request.u.ata.command,
+-            (int)iocmd.u.request.u.ata.feature,
+-            (int)iocmd.u.request.u.ata.count,
+-            (int)((iocmd.u.request.u.ata.lba) & 0xff),
+-            (int)((iocmd.u.request.u.ata.lba>>8) & 0xff),
+-            (int)((iocmd.u.request.u.ata.lba>>16) & 0xff),
+-            (int)iocmd.u.request.error);
++            (int)request.u.ata.command,
++            (int)request.u.ata.feature,
++            (int)request.u.ata.count,
++            (int)((request.u.ata.lba) & 0xff),
++            (int)((request.u.ata.lba>>8) & 0xff),
++            (int)((request.u.ata.lba>>16) & 0xff),
++            (int)request.error);
+     printwarning(BAD_SMART,buf);
+     return 0;   
+   }
+ 
+-  if ((retval=ioctl(con->atacommand, IOCATA, &iocmd))) {
+-    perror("Failed command: ");
++#ifdef IOCATAREQUEST
++  if ((retval=ioctl(con->device, IOCATAREQUEST, &request)) || request.error)
++#else
++  if ((retval=ioctl(con->atacommand, IOCATA, &iocmd)) || request.error)
++#endif
+     return -1;
+-  }
+   // 
+   if (copydata)
+     memcpy(data, buff, 512);
+@@ -483,16 +530,22 @@
+ 
+ // Interface to ATA devices behind 3ware escalade RAID controller cards.  See os_linux.c
+ 
++#define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520
++#define BUFFER_LEN_9000_CHAR ( sizeof(TW_OSLI_IOCTL_NO_DATA_BUF) + sizeof(TWE_Command) ) // 2048
++#define TW_IOCTL_BUFFER_SIZE ( MAX(BUFFER_LEN_678K_CHAR, BUFFER_LEN_9000_CHAR) )
++
+ int escalade_command_interface(int fd, int disknum, int escalade_type, smart_command_set command, int select, char *data) {
+   // to hold true file descriptor
+   struct freebsd_dev_channel* con;
+ 
+   // return value and buffer for ioctl()
+   int  ioctlreturn, readdata=0;
+-  struct twe_usercommand* cmd = NULL;
++  struct twe_usercommand* cmd_twe = NULL;
++  TW_OSLI_IOCTL_NO_DATA_BUF* cmd_twa = NULL;
++  TWE_Command_ATA* ata = NULL;
+ 
+   // Used by both the SCSI and char interfaces
+-  char ioctl_buffer[sizeof(struct twe_usercommand)];
++  char ioctl_buffer[TW_IOCTL_BUFFER_SIZE];
+ 
+   if (disknum < 0) {
+     printwarning(NO_DISK_3WARE,NULL);
+@@ -503,27 +556,40 @@
+   if (isnotopen(&fd,&con))
+       return -1;
+ 
+-  memset(ioctl_buffer, 0, sizeof(struct twe_usercommand));
++  memset(ioctl_buffer, 0, TW_IOCTL_BUFFER_SIZE);
+ 
+-  cmd = (struct twe_usercommand*)ioctl_buffer;
+-  cmd->tu_command.ata.opcode = TWE_OP_ATA_PASSTHROUGH;
++  if (escalade_type==CONTROLLER_3WARE_9000_CHAR) {
++    cmd_twa = (TW_OSLI_IOCTL_NO_DATA_BUF*)ioctl_buffer;
++    cmd_twa->pdata = ((TW_OSLI_IOCTL_WITH_PAYLOAD*)cmd_twa)->payload.data_buf;
++    cmd_twa->driver_pkt.buffer_length = 512;
++    ata = (TWE_Command_ATA*)&cmd_twa->cmd_pkt.command.cmd_pkt_7k;
++  } else if (escalade_type==CONTROLLER_3WARE_678K_CHAR) {
++    cmd_twe = (struct twe_usercommand*)ioctl_buffer;
++    ata = &cmd_twe->tu_command.ata;
++  } else {
++    pout("Unrecognized escalade_type %d in freebsd_3ware_command_interface(disk %d)\n"
++         "Please contact " PACKAGE_BUGREPORT "\n", escalade_type, disknum);
++    errno=ENOSYS;
++    return -1;
++  }
+ 
+   // Same for (almost) all commands - but some reset below
+-  cmd->tu_command.ata.request_id    = 0xFF;
+-  cmd->tu_command.ata.unit   = disknum;
+-  cmd->tu_command.ata.host_id = 0;
+-  cmd->tu_command.ata.status        = 0;           
+-  cmd->tu_command.ata.flags         = 0x1;
+-  cmd->tu_command.ata.drive_head    = 0x0;
+-  cmd->tu_command.ata.sector_num    = 0;
++  ata->opcode        = TWE_OP_ATA_PASSTHROUGH;
++  ata->request_id    = 0xFF;
++  ata->unit          = disknum;
++  ata->host_id       = 0;
++  ata->status        = 0;           
++  ata->flags         = 0x1;
++  ata->drive_head    = 0x0;
++  ata->sector_num    = 0;
+ 
+   // All SMART commands use this CL/CH signature.  These are magic
+   // values from the ATA specifications.
+-  cmd->tu_command.ata.cylinder_lo   = 0x4F;
+-  cmd->tu_command.ata.cylinder_hi   = 0xC2;
++  ata->cylinder_lo   = 0x4F;
++  ata->cylinder_hi   = 0xC2;
+   
+   // SMART ATA COMMAND REGISTER value
+-  cmd->tu_command.ata.command       = ATA_SMART_CMD;
++  ata->command       = ATA_SMART_CMD;
+   
+   // Is this a command that reads or returns 512 bytes?
+   // passthru->param values are:
+@@ -538,61 +604,63 @@
+       command == IDENTIFY        ||
+       command == WRITE_LOG ) {
+     readdata=1;
+-    cmd->tu_size = 512;
+-    cmd->tu_data = data;
+-    cmd->tu_command.ata.sgl_offset = 0x5;
+-    cmd->tu_command.ata.size         = 0x5;
+-    cmd->tu_command.ata.param        = 0xD;
+-    cmd->tu_command.ata.sector_count = 0x1;
++    if (escalade_type==CONTROLLER_3WARE_678K_CHAR) {
++      cmd_twe->tu_data = data;
++      cmd_twe->tu_size = 512;
++    }
++    ata->sgl_offset   = 0x5;
++    ata->size         = 0x5;
++    ata->param        = 0xD;
++    ata->sector_count = 0x1;
+     // For 64-bit to work correctly, up the size of the command packet
+     // in dwords by 1 to account for the 64-bit single sgl 'address'
+     // field. Note that this doesn't agree with the typedefs but it's
+     // right (agree with kernel driver behavior/typedefs).
+-    //if (sizeof(long)==8)
+-    //  cmd->tu_command.ata.size++;
++    //if (escalade_type==CONTROLLER_3WARE_9000_CHAR && sizeof(long)==8)
++    //  ata->size++;
+   }
+   else {
+     // Non data command -- but doesn't use large sector 
+     // count register values.  
+-    cmd->tu_command.ata.sgl_offset = 0x0;
+-    cmd->tu_command.ata.size         = 0x5;
+-    cmd->tu_command.ata.param        = 0x8;
+-    cmd->tu_command.ata.sector_count = 0x0;
++    ata->sgl_offset   = 0x0;
++    ata->size         = 0x5;
++    ata->param        = 0x8;
++    ata->sector_count = 0x0;
+   }
+   
+   // Now set ATA registers depending upon command
+   switch (command){
+   case CHECK_POWER_MODE:
+-    cmd->tu_command.ata.command     = ATA_CHECK_POWER_MODE;
+-    cmd->tu_command.ata.features    = 0;
+-    cmd->tu_command.ata.cylinder_lo = 0;
+-    cmd->tu_command.ata.cylinder_hi = 0;
++    ata->command     = ATA_CHECK_POWER_MODE;
++    ata->features    = 0;
++    ata->cylinder_lo = 0;
++    ata->cylinder_hi = 0;
+     break;
+   case READ_VALUES:
+-    cmd->tu_command.ata.features = ATA_SMART_READ_VALUES;
++    ata->features = ATA_SMART_READ_VALUES;
+     break;
+   case READ_THRESHOLDS:
+-    cmd->tu_command.ata.features = ATA_SMART_READ_THRESHOLDS;
++    ata->features = ATA_SMART_READ_THRESHOLDS;
+     break;
+   case READ_LOG:
+-    cmd->tu_command.ata.features = ATA_SMART_READ_LOG_SECTOR;
++    ata->features = ATA_SMART_READ_LOG_SECTOR;
+     // log number to return
+-    cmd->tu_command.ata.sector_num  = select;
++    ata->sector_num  = select;
+     break;
+   case WRITE_LOG:
+-    cmd->tu_data = data;
++    if (escalade_type==CONTROLLER_3WARE_9000_CHAR)
++      memcpy(cmd_twa->pdata, data, 512);
+     readdata=0;
+-    cmd->tu_command.ata.features     = ATA_SMART_WRITE_LOG_SECTOR;
+-    cmd->tu_command.ata.sector_count = 1;
+-    cmd->tu_command.ata.sector_num   = select;
+-    cmd->tu_command.ata.param        = 0xF;  // PIO data write
++    ata->features     = ATA_SMART_WRITE_LOG_SECTOR;
++    ata->sector_num   = select;
++    ata->param        = 0xF;  // PIO data write
+     break;
+   case IDENTIFY:
+     // ATA IDENTIFY DEVICE
+-    cmd->tu_command.ata.command     = ATA_IDENTIFY_DEVICE;
+-    cmd->tu_command.ata.features    = 0;
+-    cmd->tu_command.ata.cylinder_lo = 0;
+-    cmd->tu_command.ata.cylinder_hi = 0;
++    ata->command     = ATA_IDENTIFY_DEVICE;
++    ata->features    = 0;
++    ata->cylinder_lo = 0;
++    ata->cylinder_hi = 0;
+     break;
+   case PIDENTIFY:
+     // 3WARE controller can NOT have packet device internally
+@@ -600,34 +668,34 @@
+     errno=ENODEV;
+     return -1;
+   case ENABLE:
+-    cmd->tu_command.ata.features = ATA_SMART_ENABLE;
++    ata->features = ATA_SMART_ENABLE;
+     break;
+   case DISABLE:
+-    cmd->tu_command.ata.features = ATA_SMART_DISABLE;
++    ata->features = ATA_SMART_DISABLE;
+     break;
+   case AUTO_OFFLINE:
+-    cmd->tu_command.ata.features     = ATA_SMART_AUTO_OFFLINE;
++    ata->features     = ATA_SMART_AUTO_OFFLINE;
+     // Enable or disable?
+-    cmd->tu_command.ata.sector_count = select;
++    ata->sector_count = select;
+     break;
+   case AUTOSAVE:
+-    cmd->tu_command.ata.features     = ATA_SMART_AUTOSAVE;
++    ata->features     = ATA_SMART_AUTOSAVE;
+     // Enable or disable?
+-    cmd->tu_command.ata.sector_count = select;
++    ata->sector_count = select;
+     break;
+   case IMMEDIATE_OFFLINE:
+-    cmd->tu_command.ata.features    = ATA_SMART_IMMEDIATE_OFFLINE;
++    ata->features    = ATA_SMART_IMMEDIATE_OFFLINE;
+     // What test type to run?
+-    cmd->tu_command.ata.sector_num  = select;
++    ata->sector_num  = select;
+     break;
+   case STATUS_CHECK:
+-    cmd->tu_command.ata.features = ATA_SMART_STATUS;
++    ata->features = ATA_SMART_STATUS;
+     break;
+   case STATUS:
+     // This is JUST to see if SMART is enabled, by giving SMART status
+     // command. But it doesn't say if status was good, or failing.
+     // See below for the difference.
+-    cmd->tu_command.ata.features = ATA_SMART_STATUS;
++    ata->features = ATA_SMART_STATUS;
+     break;
+   default:
+     pout("Unrecognized command %d in freebsd_3ware_command_interface(disk %d)\n"
+@@ -637,7 +705,19 @@
+   }
+ 
+   // Now send the command down through an ioctl()
+-  ioctlreturn=ioctl(con->atacommand,TWEIO_COMMAND,cmd);
++  if (escalade_type==CONTROLLER_3WARE_9000_CHAR) {
++#ifdef IOCATAREQUEST
++    ioctlreturn=ioctl(con->device,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa);
++#else
++    ioctlreturn=ioctl(con->atacommand,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa);
++#endif
++  } else {
++#ifdef IOCATAREQUEST
++    ioctlreturn=ioctl(con->device,TWEIO_COMMAND,cmd_twe);
++#else
++    ioctlreturn=ioctl(con->atacommand,TWEIO_COMMAND,cmd_twe);
++#endif
++  }
+   
+   // Deal with the different error cases
+   if (ioctlreturn) {
+@@ -648,9 +728,9 @@
+   
+   // See if the ATA command failed.  Now that we have returned from
+   // the ioctl() call, if passthru is valid, then:
+-  // - cmd->tu_command.ata.status contains the 3ware controller STATUS
+-  // - cmd->tu_command.ata.command contains the ATA STATUS register
+-  // - cmd->tu_command.ata.features contains the ATA ERROR register
++  // - ata->status contains the 3ware controller STATUS
++  // - ata->command contains the ATA STATUS register
++  // - ata->features contains the ATA ERROR register
+   //
+   // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS
+   // If bit 0 (error bit) is set, then ATA ERROR register is valid.
+@@ -658,21 +738,27 @@
+   // doesn't make much sense: we don't care in detail why the error
+   // happened.
+   
+-  if (cmd->tu_command.ata.status || (cmd->tu_command.ata.command & 0x21)) {
+-    pout("Command failed, ata.status=(0x%2.2x), ata.command=(0x%2.2x), ata.flags=(0x%2.2x)\n",cmd->tu_command.ata.status,cmd->tu_command.ata.command,cmd->tu_command.ata.flags);
++  if (ata->status || (ata->command & 0x21)) {
++    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);
+     errno=EIO;
+     return -1;
+   }
+   
++  // If this is a read data command, copy data to output buffer
++  if (readdata) {
++    if (escalade_type==CONTROLLER_3WARE_9000_CHAR)
++      memcpy(data, cmd_twa->pdata, 512);
++  }
++
+   // For STATUS_CHECK, we need to check register values
+   if (command==STATUS_CHECK) {
+     
+     // To find out if the SMART RETURN STATUS is good or failing, we
+     // need to examine the values of the Cylinder Low and Cylinder
+     // High Registers.
+-    
+-    unsigned short cyl_lo=cmd->tu_command.ata.cylinder_lo;
+-    unsigned short cyl_hi=cmd->tu_command.ata.cylinder_hi;
++
++    unsigned short cyl_lo=ata->cylinder_lo;
++    unsigned short cyl_hi=ata->cylinder_hi;
+     
+     // If values in Cyl-LO and Cyl-HI are unchanged, SMART status is good.
+     if (cyl_lo==0x4F && cyl_hi==0xC2)
+@@ -688,7 +774,7 @@
+   
+   // copy sector count register (one byte!) to return data
+   if (command==CHECK_POWER_MODE)
+-    *data=*(char *)&(cmd->tu_command.ata.sector_count);
++    *data=*(char *)&(ata->sector_count);
+   
+   // look for nonexistent devices/ports
+   if (command==IDENTIFY && !nonempty((unsigned char *)data, 512)) {
+@@ -709,6 +795,14 @@
+   return 0;
+ }
+ 
++static int get_twa_channel_unit (const char* name, int* unit, int* dev) {
++  if (sscanf(name, "twa%d", dev) != 1)
++    return -1;
++  *unit=0; // not really needed for TWA drives, as we handle that seperately
++  return 0;
++}
++
++#ifndef IOCATAREQUEST
+ static int get_ata_channel_unit ( const char* name, int* unit, int* dev) {
+ #ifndef ATAREQUEST
+   *dev=0;
+@@ -756,7 +850,7 @@
+     return 0;
+ #endif
+ }
+-
++#endif
+ 
+ // Guess device type (ata or scsi) based on device name (FreeBSD
+ // specific) SCSI device name in FreeBSD can be sd, sr, scd, st, nst,
+@@ -768,6 +862,7 @@
+ static const char * fbsd_dev_scsi_tape2 = "nsa";
+ static const char * fbsd_dev_scsi_tape3 = "esa";
+ static const char * fbsd_dev_twe_disk = "twed";
++static const char * fbsd_dev_twa_disk = "twa";
+ 
+ static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel *chan) {
+   int len;
+@@ -788,11 +883,13 @@
+   // form /dev/ad* or ad*
+   if (!strncmp(fbsd_dev_ata_disk_prefix, dev_name,
+                strlen(fbsd_dev_ata_disk_prefix))) {
++#ifndef IOCATAREQUEST
+     if (chan != NULL) {
+       if (get_ata_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) {
+         return CONTROLLER_UNKNOWN;
+       }
+     }
++#endif
+     return CONTROLLER_ATA;
+   }
+   
+@@ -824,6 +921,16 @@
+       }
+     }
+     return CONTROLLER_3WARE_678K_CHAR;
++  }
++
++  if (!strncmp(fbsd_dev_twa_disk,dev_name,
++             strlen(fbsd_dev_twa_disk))) {
++    if (chan != NULL) {
++      if (get_twa_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) {
++      return CONTROLLER_UNKNOWN;
++      }
++    }
++    return CONTROLLER_3WARE_9000_CHAR;
+   }
+ 
+   // we failed to recognize any of the forms
diff -ruN smartmontools/files/patch-os_freebsd.h smartmontools.old/files/patch-os_freebsd.h
--- smartmontools/files/patch-os_freebsd.h      Thu Jan  1 03:00:00 1970
+++ smartmontools.old/files/patch-os_freebsd.h  Tue Apr 25 22:26:25 2006
@@ -0,0 +1,265 @@
+--- os_freebsd.h.orig  Sun Sep  5 09:16:07 2004
++++ os_freebsd.h       Sat Aug  6 21:08:54 2005
+@@ -261,6 +261,262 @@
+ 
+ #endif
+ 
++#ifdef  HAVE_SYS_TW_OSL_IOCTL_H
++#include <sys/tw_osl_ioctl.h>
++#else
++/*
++ * Following cut out of tw_osl_types.h
++ *
++ */
++
++typedef void                  TW_VOID;
++typedef char                  TW_INT8;
++typedef unsigned char         TW_UINT8;
++typedef short                 TW_INT16;
++typedef unsigned short                TW_UINT16;
++typedef int                   TW_INT32;
++typedef unsigned int          TW_UINT32;
++typedef long long             TW_INT64;
++typedef unsigned long long    TW_UINT64;
++
++/*
++ * Following cut out of tw_cl_share.h
++ *
++ */
++
++#pragma pack(1)
++
++struct tw_cl_event_packet {
++      TW_UINT32       sequence_id;
++      TW_UINT32       time_stamp_sec;
++      TW_UINT16       aen_code;
++      TW_UINT8        severity;
++      TW_UINT8        retrieved;
++      TW_UINT8        repeat_count;
++      TW_UINT8        parameter_len;
++      TW_UINT8        parameter_data[98];
++      TW_UINT32       event_src;
++      TW_UINT8        severity_str[20];
++};
++
++#pragma pack()
++
++/*
++ * Following cut out of tw_cl_fwif.h
++ *
++ */
++
++#define TWA_FW_CMD_ATA_PASSTHROUGH            0x11
++
++#define TWA_SENSE_DATA_LENGTH         18
++
++#pragma pack(1)
++/* 7000 structures. */
++struct tw_cl_command_init_connect {
++      TW_UINT8        res1__opcode;   /* 3:5 */
++      TW_UINT8        size;
++      TW_UINT8        request_id;
++      TW_UINT8        res2;
++      TW_UINT8        status;
++      TW_UINT8        flags;
++      TW_UINT16       message_credits;
++      TW_UINT32       features;
++      TW_UINT16       fw_srl;
++      TW_UINT16       fw_arch_id;
++      TW_UINT16       fw_branch;
++      TW_UINT16       fw_build;
++      TW_UINT32       result;
++};
++
++
++/* Structure for downloading firmware onto the controller. */
++struct tw_cl_command_download_firmware {
++      TW_UINT8        sgl_off__opcode;/* 3:5 */
++      TW_UINT8        size;
++      TW_UINT8        request_id;
++      TW_UINT8        unit;
++      TW_UINT8        status;
++      TW_UINT8        flags;
++      TW_UINT16       param;
++      TW_UINT8        sgl[1];
++};
++
++
++/* Structure for hard resetting the controller. */
++struct tw_cl_command_reset_firmware {
++      TW_UINT8        res1__opcode;   /* 3:5 */
++      TW_UINT8        size;
++      TW_UINT8        request_id;
++      TW_UINT8        unit;
++      TW_UINT8        status;
++      TW_UINT8        flags;
++      TW_UINT8        res2;
++      TW_UINT8        param;
++};
++
++
++/* Structure for sending get/set param commands. */
++struct tw_cl_command_param {
++      TW_UINT8        sgl_off__opcode;/* 3:5 */
++      TW_UINT8        size;
++      TW_UINT8        request_id;
++      TW_UINT8        host_id__unit;  /* 4:4 */
++      TW_UINT8        status;
++      TW_UINT8        flags;
++      TW_UINT16       param_count;
++      TW_UINT8        sgl[1];
++};
++
++
++/* Generic command packet. */
++struct tw_cl_command_generic {
++      TW_UINT8        sgl_off__opcode;/* 3:5 */
++      TW_UINT8        size;
++      TW_UINT8        request_id;
++      TW_UINT8        host_id__unit;  /* 4:4 */
++      TW_UINT8        status;
++      TW_UINT8        flags;
++      TW_UINT16       count;  /* block cnt, parameter cnt, message credits */
++};
++
++
++/* Command packet header. */
++struct tw_cl_command_header {
++      TW_UINT8        sense_data[TWA_SENSE_DATA_LENGTH];
++      struct {
++              TW_INT8         reserved[4];
++              TW_UINT16       error;
++              TW_UINT8        padding;
++              TW_UINT8        res__severity;  /* 5:3 */
++      } status_block;
++      TW_UINT8        err_specific_desc[98];
++      struct {
++              TW_UINT8        size_header;
++              TW_UINT16       reserved;
++              TW_UINT8        size_sense;
++      } header_desc;
++};
++
++
++/* 7000 Command packet. */
++union tw_cl_command_7k {
++      struct tw_cl_command_init_connect       init_connect;
++      struct tw_cl_command_download_firmware  download_fw;
++      struct tw_cl_command_reset_firmware     reset_fw;
++      struct tw_cl_command_param              param;
++      struct tw_cl_command_generic            generic;
++      TW_UINT8        padding[1024 - sizeof(struct tw_cl_command_header)];
++};
++
++
++/* 9000 Command Packet. */
++struct tw_cl_command_9k {
++      TW_UINT8        res__opcode;    /* 3:5 */
++      TW_UINT8        unit;
++      TW_UINT16       lun_l4__req_id; /* 4:12 */
++      TW_UINT8        status;
++      TW_UINT8        sgl_offset; /* offset (in bytes) to sg_list, from the
++                                      end of sgl_entries */
++      TW_UINT16       lun_h4__sgl_entries;
++      TW_UINT8        cdb[16];
++      TW_UINT8        sg_list[872];/* total struct size =
++                                      1024-sizeof(cmd_hdr) */
++};
++
++
++/* Full command packet. */
++struct tw_cl_command_packet {
++      struct tw_cl_command_header     cmd_hdr;
++      union {
++              union tw_cl_command_7k  cmd_pkt_7k;
++              struct tw_cl_command_9k cmd_pkt_9k;
++      } command;
++};
++
++#pragma pack()
++
++/*
++ * Following cut out of tw_cl_ioctl.h
++ *
++ */
++
++#pragma pack(1)
++
++/* Structure used to handle GET/RELEASE LOCK ioctls. */
++struct tw_cl_lock_packet {
++      TW_UINT32       timeout_msec;
++      TW_UINT32       time_remaining_msec;
++      TW_UINT32       force_flag;
++};
++
++
++/* Structure used to handle GET COMPATIBILITY INFO ioctl. */
++struct tw_cl_compatibility_packet {
++      TW_UINT8        driver_version[32];/* driver version */
++      TW_UINT16       working_srl;    /* driver & firmware negotiated srl */
++      TW_UINT16       working_branch; /* branch # of the firmware that the
++                                      driver is compatible with */
++      TW_UINT16       working_build;  /* build # of the firmware that the
++                                      driver is compatible with */
++};
++
++
++/* Driver understandable part of the ioctl packet built by the API. */
++struct tw_cl_driver_packet {
++      TW_UINT32       control_code;
++      TW_UINT32       status;
++      TW_UINT32       unique_id;
++      TW_UINT32       sequence_id;
++      TW_UINT32       os_status;
++      TW_UINT32       buffer_length;
++};
++
++#pragma pack()
++
++/*
++ * Following cut out of tw_osl_ioctl.h
++ *
++ */
++
++#pragma pack(1)
++/*
++ * We need the structure below to ensure that the first byte of
++ * data_buf is not overwritten by the kernel, after we return
++ * from the ioctl call.  Note that cmd_pkt has been reduced
++ * to an array of 1024 bytes even though it's actually 2048 bytes
++ * in size.  This is because, we don't expect requests from user
++ * land requiring 2048 (273 sg elements) byte cmd pkts.
++ */
++typedef struct tw_osli_ioctl_no_data_buf {
++      struct tw_cl_driver_packet      driver_pkt;
++      TW_VOID                         *pdata; /* points to data_buf */
++      TW_INT8                         padding[488 - sizeof(TW_VOID *)];
++      struct tw_cl_command_packet     cmd_pkt;
++} TW_OSLI_IOCTL_NO_DATA_BUF;
++
++#pragma pack()
++
++#define TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH            \
++      _IOWR('T', 202, TW_OSLI_IOCTL_NO_DATA_BUF)
++
++#pragma pack(1)
++
++typedef struct tw_osli_ioctl_with_payload {
++      struct tw_cl_driver_packet      driver_pkt;
++      TW_INT8                         padding[488];
++      struct tw_cl_command_packet     cmd_pkt;
++      union {
++              struct tw_cl_event_packet               event_pkt;
++              struct tw_cl_lock_packet                lock_pkt;
++              struct tw_cl_compatibility_packet       compat_pkt;
++              TW_INT8                                 data_buf[1];
++      } payload;
++} TW_OSLI_IOCTL_WITH_PAYLOAD;
++
++#pragma pack()
++
++#endif
++
+ /* 
+    The following definitions/macros/prototypes are used for three
+    different interfaces, referred to as "the three cases" below.
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200604251848.k3PImuZr095435>