MSA1000, cciss_vol_status, and FreeBSD

    Back to cciss.sourceforge.net main page


  • (Current as of Sep 7, 2007)

    So, what would it take to get cciss_vol_status to work with the MSA1000 (and similar) on FreeBSD?

    You need to port this function:

      726 int do_sg_io(int fd, unsigned char *cdb, unsigned char cdblen, unsigned char *buffer,
      727 	unsigned int buf_size, int direction)
      728 {
      729 	int status;
      730 	sg_io_hdr_t sgio;
      731 	unsigned char sensebuffer[64];
      732 
      733 	memset(buffer, 0, buf_size);
      734 	memset(&sgio, 0, sizeof(sgio));
      735 
      736 	setup_sgio(&sgio, (unsigned char *) cdb, cdblen, buffer,
      737 		buf_size, sensebuffer, sizeof(sensebuffer), direction);
      738 
      739 	status = ioctl(fd, SG_IO, &sgio);
      740 
      741 	if (status == 0 && sgio.host_status == 0 && sgio.driver_status == 0) {   /* cmd succeeded */
      742 		if (sgio.status == 0 || (sgio.status == 2 &&
      743 			(((sensebuffer[2] & 0x0f) == 0x00) || /* no error */
      744 			((sensebuffer[2] & 0x0f) == 0x01)))) {
      745 			return 0;
      746 		}
      747 		if (debug_sgio)
      748 			fprintf(stderr, "sgio cmd 0x%02x check condition, sense key = %d\n",
      749 				cdb[0], sensebuffer[2] & 0x0f);
      750 		return -1;
      751 	}
      752 	if (debug_sgio)
      753 		fprintf(stderr, "sgio ioctl: %d, cdb[0]=0x%02x, "
      754 			"status host/driver/scsi/sensekey = %d/%d/%d/0x%02x\n",
      755 			status, cdb[0], sgio.host_status, sgio.driver_status,
      756 			sgio.status, sensebuffer[2]);
      757 	return -1;
      758 }
    

    You can ignore the innards, and just implement a function with the same prototype which takes a file descriptor to the device you want to talk to, a SCSI CDB, CDB length, data buffer, and direction. The direction, as used in this program is always from the device, SG_DXFER_TO_FROM_DEV, but the possible values are these, from the linux kernel, include/scsi/sg.h:

    /* Use negative values to flag difference from original sg_header structure */
    #define SG_DXFER_NONE (-1)      /* e.g. a SCSI Test Unit Ready command */
    #define SG_DXFER_TO_DEV (-2)    /* e.g. a SCSI WRITE command */
    #define SG_DXFER_FROM_DEV (-3)  /* e.g. a SCSI READ command */
    #define SG_DXFER_TO_FROM_DEV (-4) /* treated like SG_DXFER_FROM_DEV with the
                                       additional property than during indirect
                                       IO the user buffer is copied into the
                                       kernel buffers before the transfer */
    #define SG_DXFER_UNKNOWN (-5)   /* Unknown data direction */
    

    Once a FreeBSD version of this do_sg_io function exists, I think we'll be 98% of the way towards getting the MSA1000 to be working with cciss_vol_status on FreeBSD.

    I looked into doing this myself, but it seems rather complicated and I don't know that much about FreeBSD. So I'm going to leave this task for others more knowledgeable. I can give some hints though. The sg3_utils package contains a file called sg_pt_freebsd.c, which implements a SCSI passthrough for FreeBSD. However, it's considerably more complicated than the code above, and I could not immediately see how to form a drop-in replacement for the above code for use on FreeBSD. Well, that's all the hints I have.

    It may turn out to be the case that the way FreeBSD's SCSI system works (however that may be) is such that constructing a function which takes a file descriptor as do_sg_io does and expecting to be able to send arbitrary SCSI CDBs to the device just isn't how it works. If that's the case, then obviously what I've outlined here won't work as I've described it.

    Feel free to send me a patch.