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