root/drivers/ide/ide-devsets.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_io_32bit
  2. set_ksettings
  3. set_using_dma
  4. set_pio_mode_abuse
  5. set_pio_mode
  6. set_unmaskirq
  7. ide_devset_execute
  8. ide_do_devset

   1 // SPDX-License-Identifier: GPL-2.0
   2 
   3 #include <linux/kernel.h>
   4 #include <linux/gfp.h>
   5 #include <linux/ide.h>
   6 
   7 DEFINE_MUTEX(ide_setting_mtx);
   8 
   9 ide_devset_get(io_32bit, io_32bit);
  10 
  11 static int set_io_32bit(ide_drive_t *drive, int arg)
  12 {
  13         if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT)
  14                 return -EPERM;
  15 
  16         if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))
  17                 return -EINVAL;
  18 
  19         drive->io_32bit = arg;
  20 
  21         return 0;
  22 }
  23 
  24 ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS);
  25 
  26 static int set_ksettings(ide_drive_t *drive, int arg)
  27 {
  28         if (arg < 0 || arg > 1)
  29                 return -EINVAL;
  30 
  31         if (arg)
  32                 drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS;
  33         else
  34                 drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS;
  35 
  36         return 0;
  37 }
  38 
  39 ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA);
  40 
  41 static int set_using_dma(ide_drive_t *drive, int arg)
  42 {
  43 #ifdef CONFIG_BLK_DEV_IDEDMA
  44         int err = -EPERM;
  45 
  46         if (arg < 0 || arg > 1)
  47                 return -EINVAL;
  48 
  49         if (ata_id_has_dma(drive->id) == 0)
  50                 goto out;
  51 
  52         if (drive->hwif->dma_ops == NULL)
  53                 goto out;
  54 
  55         err = 0;
  56 
  57         if (arg) {
  58                 if (ide_set_dma(drive))
  59                         err = -EIO;
  60         } else
  61                 ide_dma_off(drive);
  62 
  63 out:
  64         return err;
  65 #else
  66         if (arg < 0 || arg > 1)
  67                 return -EINVAL;
  68 
  69         return -EPERM;
  70 #endif
  71 }
  72 
  73 /*
  74  * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away
  75  */
  76 static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
  77 {
  78         switch (req_pio) {
  79         case 202:
  80         case 201:
  81         case 200:
  82         case 102:
  83         case 101:
  84         case 100:
  85                 return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0;
  86         case 9:
  87         case 8:
  88                 return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0;
  89         case 7:
  90         case 6:
  91                 return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0;
  92         default:
  93                 return 0;
  94         }
  95 }
  96 
  97 static int set_pio_mode(ide_drive_t *drive, int arg)
  98 {
  99         ide_hwif_t *hwif = drive->hwif;
 100         const struct ide_port_ops *port_ops = hwif->port_ops;
 101 
 102         if (arg < 0 || arg > 255)
 103                 return -EINVAL;
 104 
 105         if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
 106             (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
 107                 return -ENOSYS;
 108 
 109         if (set_pio_mode_abuse(drive->hwif, arg)) {
 110                 drive->pio_mode = arg + XFER_PIO_0;
 111 
 112                 if (arg == 8 || arg == 9) {
 113                         unsigned long flags;
 114 
 115                         /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */
 116                         spin_lock_irqsave(&hwif->lock, flags);
 117                         port_ops->set_pio_mode(hwif, drive);
 118                         spin_unlock_irqrestore(&hwif->lock, flags);
 119                 } else
 120                         port_ops->set_pio_mode(hwif, drive);
 121         } else {
 122                 int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
 123 
 124                 ide_set_pio(drive, arg);
 125 
 126                 if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
 127                         if (keep_dma)
 128                                 ide_dma_on(drive);
 129                 }
 130         }
 131 
 132         return 0;
 133 }
 134 
 135 ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK);
 136 
 137 static int set_unmaskirq(ide_drive_t *drive, int arg)
 138 {
 139         if (drive->dev_flags & IDE_DFLAG_NO_UNMASK)
 140                 return -EPERM;
 141 
 142         if (arg < 0 || arg > 1)
 143                 return -EINVAL;
 144 
 145         if (arg)
 146                 drive->dev_flags |= IDE_DFLAG_UNMASK;
 147         else
 148                 drive->dev_flags &= ~IDE_DFLAG_UNMASK;
 149 
 150         return 0;
 151 }
 152 
 153 ide_ext_devset_rw_sync(io_32bit, io_32bit);
 154 ide_ext_devset_rw_sync(keepsettings, ksettings);
 155 ide_ext_devset_rw_sync(unmaskirq, unmaskirq);
 156 ide_ext_devset_rw_sync(using_dma, using_dma);
 157 __IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode);
 158 
 159 int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting,
 160                        int arg)
 161 {
 162         struct request_queue *q = drive->queue;
 163         struct request *rq;
 164         int ret = 0;
 165 
 166         if (!(setting->flags & DS_SYNC))
 167                 return setting->set(drive, arg);
 168 
 169         rq = blk_get_request(q, REQ_OP_DRV_IN, 0);
 170         ide_req(rq)->type = ATA_PRIV_MISC;
 171         scsi_req(rq)->cmd_len = 5;
 172         scsi_req(rq)->cmd[0] = REQ_DEVSET_EXEC;
 173         *(int *)&scsi_req(rq)->cmd[1] = arg;
 174         ide_req(rq)->special = setting->set;
 175 
 176         blk_execute_rq(q, NULL, rq, 0);
 177         ret = scsi_req(rq)->result;
 178         blk_put_request(rq);
 179 
 180         return ret;
 181 }
 182 
 183 ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq)
 184 {
 185         int err, (*setfunc)(ide_drive_t *, int) = ide_req(rq)->special;
 186 
 187         err = setfunc(drive, *(int *)&scsi_req(rq)->cmd[1]);
 188         if (err)
 189                 scsi_req(rq)->result = err;
 190         ide_complete_rq(drive, 0, blk_rq_bytes(rq));
 191         return ide_stopped;
 192 }

/* [<][>][^][v][top][bottom][index][help] */