LCOV - code coverage report
Current view: top level - scsi - scsi_ioctl.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 147 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: scsi_ioctl.c,v 1.54 2018/04/27 08:08:06 guenther Exp $        */
       2             : /*      $NetBSD: scsi_ioctl.c,v 1.23 1996/10/12 23:23:17 christos Exp $ */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1994 Charles Hannum.  All rights reserved.
       6             :  *
       7             :  * Redistribution and use in source and binary forms, with or without
       8             :  * modification, are permitted provided that the following conditions
       9             :  * are met:
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  * 2. Redistributions in binary form must reproduce the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer in the
      14             :  *    documentation and/or other materials provided with the distribution.
      15             :  * 3. All advertising materials mentioning features or use of this software
      16             :  *    must display the following acknowledgement:
      17             :  *      This product includes software developed by Charles Hannum.
      18             :  * 4. The name of the author may not be used to endorse or promote products
      19             :  *    derived from this software without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      22             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      23             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      24             :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      25             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      26             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      27             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      28             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      29             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      30             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      31             :  */
      32             : 
      33             : /*
      34             :  * Contributed by HD Associates (hd@world.std.com).
      35             :  * Copyright (c) 1992, 1993 HD Associates
      36             :  *
      37             :  * Berkeley style copyright.
      38             :  */
      39             : 
      40             : #include <sys/param.h>
      41             : #include <sys/errno.h>
      42             : #include <sys/systm.h>
      43             : #include <sys/pool.h>
      44             : #include <sys/device.h>
      45             : #include <sys/fcntl.h>
      46             : 
      47             : #include <scsi/scsi_all.h>
      48             : #include <scsi/scsiconf.h>
      49             : 
      50             : #include <sys/scsiio.h>
      51             : #include <sys/ataio.h>
      52             : 
      53             : int                     scsi_ioc_cmd(struct scsi_link *, scsireq_t *);
      54             : int                     scsi_ioc_ata_cmd(struct scsi_link *, atareq_t *);
      55             : 
      56             : const unsigned char scsi_readsafe_cmd[256] = {
      57             :         [0x00] = 1,     /* TEST UNIT READY */
      58             :         [0x03] = 1,     /* REQUEST SENSE */
      59             :         [0x08] = 1,     /* READ(6) */
      60             :         [0x12] = 1,     /* INQUIRY */
      61             :         [0x1a] = 1,     /* MODE SENSE */
      62             :         [0x1b] = 1,     /* START STOP */
      63             :         [0x23] = 1,     /* READ FORMAT CAPACITIES */
      64             :         [0x25] = 1,     /* READ CDVD CAPACITY */
      65             :         [0x28] = 1,     /* READ(10) */
      66             :         [0x2b] = 1,     /* SEEK */
      67             :         [0x2f] = 1,     /* VERIFY(10) */
      68             :         [0x3c] = 1,     /* READ BUFFER */
      69             :         [0x3e] = 1,     /* READ LONG */
      70             :         [0x42] = 1,     /* READ SUBCHANNEL */
      71             :         [0x43] = 1,     /* READ TOC PMA ATIP */
      72             :         [0x44] = 1,     /* READ HEADER */
      73             :         [0x45] = 1,     /* PLAY AUDIO(10) */
      74             :         [0x46] = 1,     /* GET CONFIGURATION */
      75             :         [0x47] = 1,     /* PLAY AUDIO MSF */
      76             :         [0x48] = 1,     /* PLAY AUDIO TI */
      77             :         [0x4a] = 1,     /* GET EVENT STATUS NOTIFICATION */
      78             :         [0x4b] = 1,     /* PAUSE RESUME */
      79             :         [0x4e] = 1,     /* STOP PLAY SCAN */
      80             :         [0x51] = 1,     /* READ DISC INFO */
      81             :         [0x52] = 1,     /* READ TRACK RZONE INFO */
      82             :         [0x5a] = 1,     /* MODE SENSE(10) */
      83             :         [0x88] = 1,     /* READ(16) */
      84             :         [0x8f] = 1,     /* VERIFY(16) */
      85             :         [0xa4] = 1,     /* REPORT KEY */
      86             :         [0xa5] = 1,     /* PLAY AUDIO(12) */
      87             :         [0xa8] = 1,     /* READ(12) */
      88             :         [0xac] = 1,     /* GET PERFORMANCE */
      89             :         [0xad] = 1,     /* READ DVD STRUCTURE */
      90             :         [0xb9] = 1,     /* READ CD MSF */
      91             :         [0xba] = 1,     /* SCAN */
      92             :         [0xbc] = 1,     /* PLAY CD */
      93             :         [0xbd] = 1,     /* MECHANISM STATUS */
      94             :         [0xbe] = 1      /* READ CD */
      95             : };
      96             : 
      97             : int
      98           0 : scsi_ioc_cmd(struct scsi_link *link, scsireq_t *screq)
      99             : {
     100             :         struct scsi_xfer *xs;
     101             :         int err = 0;
     102             : 
     103           0 :         if (screq->cmdlen > sizeof(struct scsi_generic))
     104           0 :                 return (EFAULT);
     105           0 :         if (screq->datalen > MAXPHYS)
     106           0 :                 return (EINVAL);
     107             : 
     108           0 :         xs = scsi_xs_get(link, 0);
     109           0 :         if (xs == NULL)
     110           0 :                 return (ENOMEM);
     111             : 
     112           0 :         memcpy(xs->cmd, screq->cmd, screq->cmdlen);
     113           0 :         xs->cmdlen = screq->cmdlen;
     114             : 
     115           0 :         if (screq->datalen > 0) {
     116           0 :                 xs->data = dma_alloc(screq->datalen, PR_WAITOK | PR_ZERO);
     117           0 :                 if (xs->data == NULL) {
     118             :                         err = ENOMEM;
     119           0 :                         goto err;
     120             :                 }
     121           0 :                 xs->datalen = screq->datalen;
     122           0 :         }
     123             : 
     124           0 :         if (screq->flags & SCCMD_READ)
     125           0 :                 xs->flags |= SCSI_DATA_IN;
     126           0 :         if (screq->flags & SCCMD_WRITE) {
     127           0 :                 if (screq->datalen > 0) {
     128           0 :                         err = copyin(screq->databuf, xs->data, screq->datalen);
     129           0 :                         if (err != 0)
     130             :                                 goto err;
     131             :                 }
     132             : 
     133           0 :                 xs->flags |= SCSI_DATA_OUT;
     134           0 :         }
     135             : 
     136           0 :         xs->flags |= SCSI_SILENT;    /* User is responsible for errors. */
     137           0 :         xs->timeout = screq->timeout;
     138           0 :         xs->retries = 0; /* user must do the retries *//* ignored */
     139             : 
     140           0 :         scsi_xs_sync(xs);
     141             : 
     142           0 :         screq->retsts = 0;
     143           0 :         screq->status = xs->status;
     144           0 :         switch (xs->error) {
     145             :         case XS_NOERROR:
     146             :                 /* probably rubbish */
     147           0 :                 screq->datalen_used = xs->datalen - xs->resid;
     148           0 :                 screq->retsts = SCCMD_OK;
     149           0 :                 break;
     150             :         case XS_SENSE:
     151             : #ifdef SCSIDEBUG
     152             :                 scsi_sense_print_debug(xs);
     153             : #endif
     154           0 :                 screq->senselen_used = min(sizeof(xs->sense),
     155             :                     sizeof(screq->sense));
     156           0 :                 memcpy(screq->sense, &xs->sense, screq->senselen_used);
     157           0 :                 screq->retsts = SCCMD_SENSE;
     158           0 :                 break;
     159             :         case XS_SHORTSENSE:
     160             : #ifdef SCSIDEBUG
     161             :                 scsi_sense_print_debug(xs);
     162             : #endif
     163           0 :                 printf("XS_SHORTSENSE\n");
     164           0 :                 screq->senselen_used = min(sizeof(xs->sense),
     165             :                     sizeof(screq->sense));
     166           0 :                 memcpy(screq->sense, &xs->sense, screq->senselen_used);
     167           0 :                 screq->retsts = SCCMD_UNKNOWN;
     168           0 :                 break;
     169             :         case XS_DRIVER_STUFFUP:
     170           0 :                 screq->retsts = SCCMD_UNKNOWN;
     171           0 :                 break;
     172             :         case XS_TIMEOUT:
     173           0 :                 screq->retsts = SCCMD_TIMEOUT;
     174           0 :                 break;
     175             :         case XS_BUSY:
     176           0 :                 screq->retsts = SCCMD_BUSY;
     177           0 :                 break;
     178             :         default:
     179           0 :                 screq->retsts = SCCMD_UNKNOWN;
     180           0 :                 break;
     181             :         }
     182             : 
     183           0 :         if (screq->datalen > 0 && screq->flags & SCCMD_READ) {
     184           0 :                 err = copyout(xs->data, screq->databuf, screq->datalen);
     185           0 :                 if (err != 0)
     186             :                         goto err;
     187             :         }
     188             : 
     189             : err:
     190           0 :         if (xs->data)
     191           0 :                 dma_free(xs->data, screq->datalen);
     192           0 :         scsi_xs_put(xs);
     193             : 
     194           0 :         return (err);
     195           0 : }
     196             : 
     197             : int
     198           0 : scsi_ioc_ata_cmd(struct scsi_link *link, atareq_t *atareq)
     199             : {
     200             :         struct scsi_xfer *xs;
     201             :         struct scsi_ata_passthru_12 *cdb;
     202             :         int err = 0;
     203             : 
     204           0 :         if (atareq->datalen > MAXPHYS)
     205           0 :                 return (EINVAL);
     206             : 
     207           0 :         xs = scsi_xs_get(link, 0);
     208           0 :         if (xs == NULL)
     209           0 :                 return (ENOMEM);
     210             : 
     211           0 :         cdb = (struct scsi_ata_passthru_12 *)xs->cmd;
     212           0 :         cdb->opcode = ATA_PASSTHRU_12;
     213             : 
     214           0 :         if (atareq->datalen > 0) {
     215           0 :                 if (atareq->flags & ATACMD_READ) {
     216           0 :                         cdb->count_proto = ATA_PASSTHRU_PROTO_PIO_DATAIN;
     217           0 :                         cdb->flags = ATA_PASSTHRU_T_DIR_READ;
     218           0 :                 } else {
     219           0 :                         cdb->count_proto = ATA_PASSTHRU_PROTO_PIO_DATAOUT;
     220           0 :                         cdb->flags = ATA_PASSTHRU_T_DIR_WRITE;
     221             :                 }
     222           0 :                 cdb->flags |= ATA_PASSTHRU_T_LEN_SECTOR_COUNT;
     223           0 :         } else {
     224           0 :                 cdb->count_proto = ATA_PASSTHRU_PROTO_NON_DATA;
     225           0 :                 cdb->flags = ATA_PASSTHRU_T_LEN_NONE;
     226             :         }
     227           0 :         cdb->features = atareq->features;
     228           0 :         cdb->sector_count = atareq->sec_count;
     229           0 :         cdb->lba_low = atareq->sec_num;
     230           0 :         cdb->lba_mid = atareq->cylinder;
     231           0 :         cdb->lba_high = atareq->cylinder >> 8;
     232           0 :         cdb->device = atareq->head & 0x0f;
     233           0 :         cdb->command = atareq->command;
     234             : 
     235           0 :         xs->cmdlen = sizeof(*cdb);
     236             : 
     237           0 :         if (atareq->datalen > 0) {
     238           0 :                 xs->data = dma_alloc(atareq->datalen, PR_WAITOK | PR_ZERO);
     239           0 :                 if (xs->data == NULL) {
     240             :                         err = ENOMEM;
     241           0 :                         goto err;
     242             :                 }
     243           0 :                 xs->datalen = atareq->datalen;
     244           0 :         }
     245             : 
     246           0 :         if (atareq->flags & ATACMD_READ)
     247           0 :                 xs->flags |= SCSI_DATA_IN;
     248           0 :         if (atareq->flags & ATACMD_WRITE) {
     249           0 :                 if (atareq->datalen > 0) {
     250           0 :                         err = copyin(atareq->databuf, xs->data,
     251             :                             atareq->datalen);
     252           0 :                         if (err != 0)
     253             :                                 goto err;
     254             :                 }
     255             : 
     256           0 :                 xs->flags |= SCSI_DATA_OUT;
     257           0 :         }
     258             : 
     259           0 :         xs->flags |= SCSI_SILENT;    /* User is responsible for errors. */
     260           0 :         xs->retries = 0; /* user must do the retries *//* ignored */
     261             : 
     262           0 :         scsi_xs_sync(xs);
     263             : 
     264           0 :         atareq->retsts = ATACMD_ERROR;
     265           0 :         switch (xs->error) {
     266             :         case XS_SENSE:
     267             :         case XS_SHORTSENSE:
     268             : #ifdef SCSIDEBUG
     269             :                 scsi_sense_print_debug(xs);
     270             : #endif
     271             :                 /* XXX this is not right */
     272             :         case XS_NOERROR:
     273           0 :                 atareq->retsts = ATACMD_OK;
     274           0 :                 break;
     275             :         default:
     276           0 :                 atareq->retsts = ATACMD_ERROR;
     277           0 :                 break;
     278             :         }
     279             : 
     280           0 :         if (atareq->datalen > 0 && atareq->flags & ATACMD_READ) {
     281           0 :                 err = copyout(xs->data, atareq->databuf, atareq->datalen);
     282           0 :                 if (err != 0)
     283             :                         goto err;
     284             :         }
     285             : 
     286             : err:
     287           0 :         if (xs->data)
     288           0 :                 dma_free(xs->data, atareq->datalen);
     289           0 :         scsi_xs_put(xs);
     290             : 
     291           0 :         return (err);
     292           0 : }
     293             : 
     294             : /*
     295             :  * Something (e.g. another driver) has called us
     296             :  * with a scsi_link for a target/lun/adapter, and a scsi
     297             :  * specific ioctl to perform, better try.
     298             :  */
     299             : int
     300           0 : scsi_do_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag)
     301             : {
     302             :         SC_DEBUG(link, SDEV_DB2, ("scsi_do_ioctl(0x%lx)\n", cmd));
     303             : 
     304           0 :         switch(cmd) {
     305             :         case SCIOCIDENTIFY: {
     306           0 :                 struct scsi_addr *sca = (struct scsi_addr *)addr;
     307             : 
     308           0 :                 if ((link->flags & (SDEV_ATAPI | SDEV_UMASS)) == 0)
     309             :                         /* A 'real' SCSI target. */
     310           0 :                         sca->type = TYPE_SCSI;
     311             :                 else
     312             :                         /* An 'emulated' SCSI target. */
     313           0 :                         sca->type = TYPE_ATAPI;
     314           0 :                 sca->scbus = link->bus->sc_dev.dv_unit;
     315           0 :                 sca->target = link->target;
     316           0 :                 sca->lun = link->lun;
     317             :                 return (0);
     318             :         }
     319             :         case SCIOCCOMMAND:
     320           0 :                 if (scsi_readsafe_cmd[((scsireq_t *)addr)->cmd[0]])
     321             :                         break;
     322             :                 /* FALLTHROUGH */
     323             :         case ATAIOCCOMMAND:
     324             :         case SCIOCDEBUG:
     325           0 :                 if ((flag & FWRITE) == 0)
     326           0 :                         return (EPERM);
     327             :                 break;
     328             :         default:
     329           0 :                 if (link->adapter->ioctl)
     330           0 :                         return ((link->adapter->ioctl)(link, cmd, addr,
     331             :                             flag));
     332             :                 else
     333           0 :                         return (ENOTTY);
     334             :         }
     335             : 
     336           0 :         switch(cmd) {
     337             :         case SCIOCCOMMAND:
     338           0 :                 return (scsi_ioc_cmd(link, (scsireq_t *)addr));
     339             :         case ATAIOCCOMMAND:
     340           0 :                 return (scsi_ioc_ata_cmd(link, (atareq_t *)addr));
     341             :         case SCIOCDEBUG: {
     342           0 :                 int level = *((int *)addr);
     343             : 
     344             :                 SC_DEBUG(link, SDEV_DB3, ("debug set to %d\n", level));
     345           0 :                 link->flags &= ~SDEV_DBX; /* clear debug bits */
     346           0 :                 if (level & 1)
     347           0 :                         link->flags |= SDEV_DB1;
     348           0 :                 if (level & 2)
     349           0 :                         link->flags |= SDEV_DB2;
     350           0 :                 if (level & 4)
     351           0 :                         link->flags |= SDEV_DB3;
     352           0 :                 if (level & 8)
     353           0 :                         link->flags |= SDEV_DB4;
     354             :                 return (0);
     355             :         }
     356             :         default:
     357             : #ifdef DIAGNOSTIC
     358           0 :                 panic("scsi_do_ioctl: impossible cmd (%#lx)", cmd);
     359             : #endif
     360             :                 return (0);
     361             :         }
     362           0 : }

Generated by: LCOV version 1.13