tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Implement mode_select for atapi tape drives



On Sat, 8 Aug 2009, Marc Balmer wrote:

But the calculated value of *_select_len is actually passed to routine scsipi_mode_select() a little bit later on, so we still need the calculated value.

why cant sizeof be used there, too?

It actually controls amount of data that is sent to the device. Most devices have 0 bytes for st->page_0_size but some have 12 bytes.


The attached patch revision includes the change to use sizeof() in the calls to memset(), adds a KASSERT when loading the quirk data to ensure that the st->page_0_size is not larger than MAX_PAGE_0_SIZE, and adds the necessary quirk for my tape drive.

Additional comments/criticisms welcomed!



-------------------------------------------------------------------------
|   Paul Goyette   | PGP DSS Key fingerprint: |  E-mail addresses:      |
| Customer Service | FA29 0E3B 35AF E8AE 6651 |  paul at whooppee.com   |
| Network Engineer | 0786 F758 55DE 53BA 7731 | pgoyette at juniper.net |
| Kernel Developer |                          | pgoyette at netbsd.org  |
-------------------------------------------------------------------------
Index: st.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/st.c,v
retrieving revision 1.211
diff -u -p -r1.211 st.c
--- st.c        12 May 2009 14:44:31 -0000      1.211
+++ st.c        8 Aug 2009 13:23:14 -0000
@@ -306,6 +306,13 @@ static const struct st_quirk_inquiry_pat
                {0, 0, 0},                             /* minor 8-11 */
                {0, 0, 0}                              /* minor 12-15 */
        }}},
+       {{T_SEQUENTIAL, T_REMOV,
+        "Seagate STT3401A", "hp0atxa", ""},    {ST_Q_ATAPI_MODESEL, 0, {
+               {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 0-3 */
+               {ST_Q_FORCE_BLKSIZE, 1024, 0},          /* minor 4-7 */
+               {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 8-11 */
+               {ST_Q_FORCE_BLKSIZE, 512, 0}            /* minor 12-15 */
+       }}},
 };
 
 #define NOEJECT 0
@@ -488,6 +495,7 @@ st_identify_drive(struct st_softc *st, s
                st->drive_quirks = finger->quirkdata.quirks;
                st->quirks = finger->quirkdata.quirks;  /* start value */
                st->page_0_size = finger->quirkdata.page_0_size;
+               KASSERT(st->page_0_size <= MAX_PAGE_0_SIZE);
                st_loadquirks(st);
        }
 }
Index: st_atapi.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/st_atapi.c,v
retrieving revision 1.22
diff -u -p -r1.22 st_atapi.c
--- st_atapi.c  12 May 2009 14:44:31 -0000      1.22
+++ st_atapi.c  8 Aug 2009 13:23:14 -0000
@@ -46,6 +46,7 @@ __KERNEL_RCSID(0, "$NetBSD: st_atapi.c,v
 
 #include <dev/scsipi/stvar.h>
 #include <dev/scsipi/atapi_tape.h>
+#include <dev/scsipi/scsi_spc.h>
 
 static int     st_atapibus_match(device_t, cfdata_t, void *);
 static void    st_atapibus_attach(device_t, device_t, void *);
@@ -177,8 +178,41 @@ st_atapibus_mode_sense(struct st_softc *
        return error;
 }
 
+/*
+ * Send a filled out parameter structure to the drive to
+ * set it into the desire modes etc.
+ */
 static int
 st_atapibus_mode_select(struct st_softc *st, int flags)
 {
-       return ENODEV; /* for now ... */
+       u_int atapi_select_len;
+       struct atapi_select {
+               struct scsi_mode_parameter_header_6  header;
+               struct scsi_general_block_descriptor blk_desc;
+               u_char sense_data[MAX_PAGE_0_SIZE];
+       } atapi_select;
+       struct scsipi_periph *periph = st->sc_periph;
+
+       if (!(st->quirkdata->quirks & ST_Q_ATAPI_MODESEL))
+               return ENODEV;
+
+       atapi_select_len = 12 + st->page_0_size;
+
+       /*
+        * Set up for a mode select
+        */
+       memset(&atapi_select, 0, sizeof(atapi_select));
+       atapi_select.header.blk_desc_len = sizeof(struct 
scsi_general_block_descriptor);
+       atapi_select.blk_desc.density = st->density;
+       if (st->flags & ST_FIXEDBLOCKS)
+               _lto3b(st->blksize, atapi_select.blk_desc.blklen);
+       if (st->page_0_size)
+               memcpy(atapi_select.sense_data, st->sense_data, 
st->page_0_size);
+
+       /*
+        * do the command
+        */
+       return scsipi_mode_select(periph, 0, &atapi_select.header,
+           atapi_select_len, flags | XS_CTL_DATA_ONSTACK,
+           ST_RETRIES, ST_CTL_TIME);
 }
Index: st_scsi.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/st_scsi.c,v
retrieving revision 1.29
diff -u -p -r1.29 st_scsi.c
--- st_scsi.c   12 May 2009 14:44:31 -0000      1.29
+++ st_scsi.c   8 Aug 2009 13:23:14 -0000
@@ -254,7 +254,7 @@ st_scsibus_mode_select(struct st_softc *
        /*
         * Set up for a mode select
         */
-       memset(&scsi_select, 0, scsi_select_len);
+       memset(&scsi_select, 0, sizeof(scsi_select));
        scsi_select.header.blk_desc_len = sizeof(struct 
scsi_general_block_descriptor);
        scsi_select.header.dev_spec &= ~SMH_DSP_BUFF_MODE;
        scsi_select.blk_desc.density = st->density;
Index: stvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/stvar.h,v
retrieving revision 1.19
diff -u -p -r1.19 stvar.h
--- stvar.h     12 May 2009 14:44:31 -0000      1.19
+++ stvar.h     8 Aug 2009 13:23:14 -0000
@@ -79,6 +79,7 @@ struct quirkdata {
 #define        ST_Q_NOPREVENT          0x0020  /* does not support PREVENT */
 #define        ST_Q_ERASE_NOIMM        0x0040  /* drive rejects ERASE/w Immed 
bit */
 #define        ST_Q_NOFILEMARKS        0x0080  /* can only write 0 filemarks */
+#define        ST_Q_ATAPI_MODESEL      0x0100  /* ATAPI drive does SCSI Mode 
Select */
        u_int page_0_size;
 #define        MAX_PAGE_0_SIZE 64
        struct modes modes[4];


Home | Main Index | Thread Index | Old Index