ide-io-std.c 7.7 KB
Newer Older
1 2 3 4

#include <linux/kernel.h>
#include <linux/ide.h>

5 6 7 8 9 10 11
#if defined(CONFIG_ARM) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) || \
    defined(CONFIG_PARISC) || defined(CONFIG_PPC) || defined(CONFIG_SPARC)
#include <asm/ide.h>
#else
#include <asm-generic/ide_iops.h>
#endif

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
/*
 *	Conventional PIO operations for ATA devices
 */

static u8 ide_inb(unsigned long port)
{
	return (u8) inb(port);
}

static void ide_outb(u8 val, unsigned long port)
{
	outb(val, port);
}

/*
 *	MMIO operations, typically used for SATA controllers
 */

static u8 ide_mm_inb(unsigned long port)
{
	return (u8) readb((void __iomem *) port);
}

static void ide_mm_outb(u8 value, unsigned long port)
{
	writeb(value, (void __iomem *) port);
}

void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
{
	if (hwif->host_flags & IDE_HFLAG_MMIO)
		writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
	else
		outb(cmd, hwif->io_ports.command_addr);
}
EXPORT_SYMBOL_GPL(ide_exec_command);

u8 ide_read_status(ide_hwif_t *hwif)
{
	if (hwif->host_flags & IDE_HFLAG_MMIO)
		return readb((void __iomem *)hwif->io_ports.status_addr);
	else
		return inb(hwif->io_ports.status_addr);
}
EXPORT_SYMBOL_GPL(ide_read_status);

u8 ide_read_altstatus(ide_hwif_t *hwif)
{
	if (hwif->host_flags & IDE_HFLAG_MMIO)
		return readb((void __iomem *)hwif->io_ports.ctl_addr);
	else
		return inb(hwif->io_ports.ctl_addr);
}
EXPORT_SYMBOL_GPL(ide_read_altstatus);

67
void ide_write_devctl(ide_hwif_t *hwif, u8 ctl)
68 69 70 71 72 73
{
	if (hwif->host_flags & IDE_HFLAG_MMIO)
		writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
	else
		outb(ctl, hwif->io_ports.ctl_addr);
}
74
EXPORT_SYMBOL_GPL(ide_write_devctl);
75

76 77 78 79 80 81 82 83 84 85 86 87
void ide_dev_select(ide_drive_t *drive)
{
	ide_hwif_t *hwif = drive->hwif;
	u8 select = drive->select | ATA_DEVICE_OBS;

	if (hwif->host_flags & IDE_HFLAG_MMIO)
		writeb(select, (void __iomem *)hwif->io_ports.device_addr);
	else
		outb(select, hwif->io_ports.device_addr);
}
EXPORT_SYMBOL_GPL(ide_dev_select);

88
void ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd)
89 90 91
{
	ide_hwif_t *hwif = drive->hwif;
	struct ide_io_ports *io_ports = &hwif->io_ports;
92
	struct ide_taskfile *tf = &cmd->hob;
93
	void (*tf_outb)(u8 addr, unsigned long port);
94
	u8 valid = cmd->valid.out.hob;
95
	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
96
	u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
97 98 99 100 101 102

	if (mmio)
		tf_outb = ide_mm_outb;
	else
		tf_outb = ide_outb;

103
	if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED)
104 105
		HIHI = 0xFF;

106
	if (valid & IDE_VALID_FEATURE)
107
		tf_outb(tf->feature, io_ports->feature_addr);
108
	if (valid & IDE_VALID_NSECT)
109
		tf_outb(tf->nsect, io_ports->nsect_addr);
110
	if (valid & IDE_VALID_LBAL)
111
		tf_outb(tf->lbal, io_ports->lbal_addr);
112
	if (valid & IDE_VALID_LBAM)
113
		tf_outb(tf->lbam, io_ports->lbam_addr);
114
	if (valid & IDE_VALID_LBAH)
115
		tf_outb(tf->lbah, io_ports->lbah_addr);
116

117
	tf = &cmd->tf;
118 119 120
	valid = cmd->valid.out.tf;

	if (valid & IDE_VALID_FEATURE)
121
		tf_outb(tf->feature, io_ports->feature_addr);
122
	if (valid & IDE_VALID_NSECT)
123
		tf_outb(tf->nsect, io_ports->nsect_addr);
124
	if (valid & IDE_VALID_LBAL)
125
		tf_outb(tf->lbal, io_ports->lbal_addr);
126
	if (valid & IDE_VALID_LBAM)
127
		tf_outb(tf->lbam, io_ports->lbam_addr);
128
	if (valid & IDE_VALID_LBAH)
129 130
		tf_outb(tf->lbah, io_ports->lbah_addr);

131
	if (valid & IDE_VALID_DEVICE)
132 133 134 135 136
		tf_outb((tf->device & HIHI) | drive->select,
			 io_ports->device_addr);
}
EXPORT_SYMBOL_GPL(ide_tf_load);

137
void ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd)
138 139 140
{
	ide_hwif_t *hwif = drive->hwif;
	struct ide_io_ports *io_ports = &hwif->io_ports;
141
	struct ide_taskfile *tf = &cmd->tf;
142 143
	void (*tf_outb)(u8 addr, unsigned long port);
	u8 (*tf_inb)(unsigned long port);
144
	u8 valid = cmd->valid.in.tf;
145 146 147 148 149 150 151 152 153 154 155
	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;

	if (mmio) {
		tf_outb = ide_mm_outb;
		tf_inb  = ide_mm_inb;
	} else {
		tf_outb = ide_outb;
		tf_inb  = ide_inb;
	}

	/* be sure we're looking at the low order bits */
S
Sergei Shtylyov 已提交
156
	tf_outb(ATA_DEVCTL_OBS, io_ports->ctl_addr);
157

158
	if (valid & IDE_VALID_ERROR)
159
		tf->error  = tf_inb(io_ports->feature_addr);
160
	if (valid & IDE_VALID_NSECT)
161
		tf->nsect  = tf_inb(io_ports->nsect_addr);
162
	if (valid & IDE_VALID_LBAL)
163
		tf->lbal   = tf_inb(io_ports->lbal_addr);
164
	if (valid & IDE_VALID_LBAM)
165
		tf->lbam   = tf_inb(io_ports->lbam_addr);
166
	if (valid & IDE_VALID_LBAH)
167
		tf->lbah   = tf_inb(io_ports->lbah_addr);
168
	if (valid & IDE_VALID_DEVICE)
169 170
		tf->device = tf_inb(io_ports->device_addr);

171
	if (cmd->tf_flags & IDE_TFLAG_LBA48) {
S
Sergei Shtylyov 已提交
172
		tf_outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr);
173

174
		tf = &cmd->hob;
175 176 177
		valid = cmd->valid.in.hob;

		if (valid & IDE_VALID_ERROR)
178
			tf->error = tf_inb(io_ports->feature_addr);
179
		if (valid & IDE_VALID_NSECT)
180
			tf->nsect = tf_inb(io_ports->nsect_addr);
181
		if (valid & IDE_VALID_LBAL)
182
			tf->lbal  = tf_inb(io_ports->lbal_addr);
183
		if (valid & IDE_VALID_LBAM)
184
			tf->lbam  = tf_inb(io_ports->lbam_addr);
185
		if (valid & IDE_VALID_LBAH)
186
			tf->lbah  = tf_inb(io_ports->lbah_addr);
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
	}
}
EXPORT_SYMBOL_GPL(ide_tf_read);

/*
 * Some localbus EIDE interfaces require a special access sequence
 * when using 32-bit I/O instructions to transfer data.  We call this
 * the "vlb_sync" sequence, which consists of three successive reads
 * of the sector count register location, with interrupts disabled
 * to ensure that the reads all happen together.
 */
static void ata_vlb_sync(unsigned long port)
{
	(void)inb(port);
	(void)inb(port);
	(void)inb(port);
}

/*
 * This is used for most PIO data transfers *from* the IDE interface
 *
 * These routines will round up any request for an odd number of bytes,
 * so if an odd len is specified, be sure that there's at least one
 * extra byte allocated for the buffer.
 */
212
void ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf,
213 214 215 216 217
		    unsigned int len)
{
	ide_hwif_t *hwif = drive->hwif;
	struct ide_io_ports *io_ports = &hwif->io_ports;
	unsigned long data_addr = io_ports->data_addr;
218
	unsigned int words = (len + 1) >> 1;
219 220 221 222 223 224 225 226 227 228 229
	u8 io_32bit = drive->io_32bit;
	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;

	if (io_32bit) {
		unsigned long uninitialized_var(flags);

		if ((io_32bit & 2) && !mmio) {
			local_irq_save(flags);
			ata_vlb_sync(io_ports->nsect_addr);
		}

230
		words >>= 1;
231
		if (mmio)
232
			__ide_mm_insl((void __iomem *)data_addr, buf, words);
233
		else
234
			insl(data_addr, buf, words);
235 236 237 238

		if ((io_32bit & 2) && !mmio)
			local_irq_restore(flags);

239 240 241 242 243
		if (((len + 1) & 3) < 2)
			return;

		buf += len & ~3;
		words = 1;
244
	}
245 246 247 248 249

	if (mmio)
		__ide_mm_insw((void __iomem *)data_addr, buf, words);
	else
		insw(data_addr, buf, words);
250 251 252 253 254 255
}
EXPORT_SYMBOL_GPL(ide_input_data);

/*
 * This is used for most PIO data transfers *to* the IDE interface
 */
256
void ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf,
257 258 259 260 261
		     unsigned int len)
{
	ide_hwif_t *hwif = drive->hwif;
	struct ide_io_ports *io_ports = &hwif->io_ports;
	unsigned long data_addr = io_ports->data_addr;
262
	unsigned int words = (len + 1) >> 1;
263 264 265 266 267 268 269 270 271 272 273
	u8 io_32bit = drive->io_32bit;
	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;

	if (io_32bit) {
		unsigned long uninitialized_var(flags);

		if ((io_32bit & 2) && !mmio) {
			local_irq_save(flags);
			ata_vlb_sync(io_ports->nsect_addr);
		}

274
		words >>= 1;
275
		if (mmio)
276
			__ide_mm_outsl((void __iomem *)data_addr, buf, words);
277
		else
278
			outsl(data_addr, buf, words);
279 280 281 282

		if ((io_32bit & 2) && !mmio)
			local_irq_restore(flags);

283 284 285 286 287
		if (((len + 1) & 3) < 2)
			return;

		buf += len & ~3;
		words = 1;
288
	}
289 290 291 292 293

	if (mmio)
		__ide_mm_outsw((void __iomem *)data_addr, buf, words);
	else
		outsw(data_addr, buf, words);
294 295 296 297 298 299 300
}
EXPORT_SYMBOL_GPL(ide_output_data);

const struct ide_tp_ops default_tp_ops = {
	.exec_command		= ide_exec_command,
	.read_status		= ide_read_status,
	.read_altstatus		= ide_read_altstatus,
301
	.write_devctl		= ide_write_devctl,
302

303
	.dev_select		= ide_dev_select,
304 305 306 307 308 309
	.tf_load		= ide_tf_load,
	.tf_read		= ide_tf_read,

	.input_data		= ide_input_data,
	.output_data		= ide_output_data,
};