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>