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