at v2.6.34-rc1 190 lines 3.9 kB view raw
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 drive->pio_mode = arg + XFER_PIO_0; 109 110 if (arg == 8 || arg == 9) { 111 unsigned long flags; 112 113 /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */ 114 spin_lock_irqsave(&hwif->lock, flags); 115 port_ops->set_pio_mode(hwif, drive); 116 spin_unlock_irqrestore(&hwif->lock, flags); 117 } else 118 port_ops->set_pio_mode(hwif, drive); 119 } else { 120 int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); 121 122 ide_set_pio(drive, arg); 123 124 if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) { 125 if (keep_dma) 126 ide_dma_on(drive); 127 } 128 } 129 130 return 0; 131} 132 133ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK); 134 135static int set_unmaskirq(ide_drive_t *drive, int arg) 136{ 137 if (drive->dev_flags & IDE_DFLAG_NO_UNMASK) 138 return -EPERM; 139 140 if (arg < 0 || arg > 1) 141 return -EINVAL; 142 143 if (arg) 144 drive->dev_flags |= IDE_DFLAG_UNMASK; 145 else 146 drive->dev_flags &= ~IDE_DFLAG_UNMASK; 147 148 return 0; 149} 150 151ide_ext_devset_rw_sync(io_32bit, io_32bit); 152ide_ext_devset_rw_sync(keepsettings, ksettings); 153ide_ext_devset_rw_sync(unmaskirq, unmaskirq); 154ide_ext_devset_rw_sync(using_dma, using_dma); 155__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode); 156 157int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, 158 int arg) 159{ 160 struct request_queue *q = drive->queue; 161 struct request *rq; 162 int ret = 0; 163 164 if (!(setting->flags & DS_SYNC)) 165 return setting->set(drive, arg); 166 167 rq = blk_get_request(q, READ, __GFP_WAIT); 168 rq->cmd_type = REQ_TYPE_SPECIAL; 169 rq->cmd_len = 5; 170 rq->cmd[0] = REQ_DEVSET_EXEC; 171 *(int *)&rq->cmd[1] = arg; 172 rq->special = setting->set; 173 174 if (blk_execute_rq(q, NULL, rq, 0)) 175 ret = rq->errors; 176 blk_put_request(rq); 177 178 return ret; 179} 180 181ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq) 182{ 183 int err, (*setfunc)(ide_drive_t *, int) = rq->special; 184 185 err = setfunc(drive, *(int *)&rq->cmd[1]); 186 if (err) 187 rq->errors = err; 188 ide_complete_rq(drive, err, blk_rq_bytes(rq)); 189 return ide_stopped; 190}