Blame view

drivers/ide/qd65xx.c 10.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
9
10
11
12
13
   *  Copyright (C) 1996-2001  Linus Torvalds & author (see below)
   */
  
  /*
   *  Version 0.03	Cleaned auto-tune, added probe
   *  Version 0.04	Added second channel tuning
   *  Version 0.05	Enhanced tuning ; added qd6500 support
   *  Version 0.06	Added dos driver's list
   *  Version 0.07	Second channel bug fix 
   *
   * QDI QD6500/QD6580 EIDE controller fast support
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
   * To activate controller support, use "ide0=qd65xx"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
   */
  
  /*
   * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
519353551   Samuel Thibault   Fix my email addr...
19
   * Samuel Thibault <samuel.thibault@ens-lyon.org>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
26
27
28
  #include <linux/types.h>
  #include <linux/kernel.h>
  #include <linux/delay.h>
  #include <linux/timer.h>
  #include <linux/mm.h>
  #include <linux/ioport.h>
  #include <linux/blkdev.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
  #include <linux/ide.h>
  #include <linux/init.h>
  #include <asm/system.h>
  #include <asm/io.h>
d92f1a282   Bartlomiej Zolnierkiewicz   ide: manage I/O r...
33
  #define DRV_NAME "qd65xx"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  #include "qd65xx.h"
  
  /*
   * I/O ports are 0x30-0x31 (and 0x32-0x33 for qd6580)
   *            or 0xb0-0xb1 (and 0xb2-0xb3 for qd6580)
   *	-- qd6500 is a single IDE interface
   *	-- qd6580 is a dual IDE interface
   *
   * More research on qd6580 being done by willmore@cig.mot.com (David)
   * More Information given by Petr Soucek (petr@ryston.cz)
   * http://www.ryston.cz/petr/vlb
   */
  
  /*
   * base: Timer1
   *
   *
   * base+0x01: Config (R/O)
   *
   * bit 0: ide baseport: 1 = 0x1f0 ; 0 = 0x170 (only useful for qd6500)
   * bit 1: qd65xx baseport: 1 = 0xb0 ; 0 = 0x30
   * bit 2: ID3: bus speed: 1 = <=33MHz ; 0 = >33MHz
   * bit 3: qd6500: 1 = disabled, 0 = enabled
   *        qd6580: 1
   * upper nibble:
   *        qd6500: 1100
   *        qd6580: either 1010 or 0101
   *
   *
   * base+0x02: Timer2 (qd6580 only)
   *
   *
   * base+0x03: Control (qd6580 only)
   *
   * bits 0-3 must always be set 1
   * bit 4 must be set 1, but is set 0 by dos driver while measuring vlb clock
   * bit 0 : 1 = Only primary port enabled : channel 0 for hda, channel 1 for hdb
   *         0 = Primary and Secondary ports enabled : channel 0 for hda & hdb
   *                                                   channel 1 for hdc & hdd
   * bit 1 : 1 = only disks on primary port
   *         0 = disks & ATAPI devices on primary port
   * bit 2-4 : always 0
   * bit 5 : status, but of what ?
   * bit 6 : always set 1 by dos driver
   * bit 7 : set 1 for non-ATAPI devices on primary port
   *	(maybe read-ahead and post-write buffer ?)
   */
  
  static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  /*
d07616f19   Bartlomiej Zolnierkiewicz   qd65xx: always us...
84
   * qd65xx_select:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
   *
d07616f19   Bartlomiej Zolnierkiewicz   qd65xx: always us...
86
   * This routine is invoked to prepare for access to a given drive.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
   */
abb596b25   Sergei Shtylyov   ide: turn selectp...
88
  static void qd65xx_dev_select(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
91
92
93
  {
  	u8 index = ((	(QD_TIMREG(drive)) & 0x80 ) >> 7) |
  			(QD_TIMREG(drive) & 0x02);
  
  	if (timings[index] != QD_TIMING(drive))
c196567a8   Bartlomiej Zolnierkiewicz   qd65xx: remove po...
94
  		outb(timings[index] = QD_TIMING(drive), QD_TIMREG(drive));
abb596b25   Sergei Shtylyov   ide: turn selectp...
95
96
  
  	outb(drive->select | ATA_DEVICE_OBS, drive->hwif->io_ports.device_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
99
100
101
102
103
104
105
106
107
108
  }
  
  /*
   * qd6500_compute_timing
   *
   * computes the timing value where
   *	lower nibble represents active time,   in count of VLB clocks
   *	upper nibble represents recovery time, in count of VLB clocks
   */
  
  static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time)
  {
30e5ee4d1   Bartlomiej Zolnierkiewicz   ide: remove obsol...
109
  	int clk = ide_vlb_clk ? ide_vlb_clk : 50;
ebae41a5a   Bartlomiej Zolnierkiewicz   ide: add "vlb|pci...
110
  	u8 act_cyc, rec_cyc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111

ebae41a5a   Bartlomiej Zolnierkiewicz   ide: add "vlb|pci...
112
113
114
  	if (clk <= 33) {
  		act_cyc =  9 - IDE_IN(active_time   * clk / 1000 + 1, 2,  9);
  		rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 0, 15);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
  	} else {
ebae41a5a   Bartlomiej Zolnierkiewicz   ide: add "vlb|pci...
116
117
  		act_cyc =  8 - IDE_IN(active_time   * clk / 1000 + 1, 1,  8);
  		rec_cyc = 18 - IDE_IN(recovery_time * clk / 1000 + 1, 3, 18);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
  	}
ebae41a5a   Bartlomiej Zolnierkiewicz   ide: add "vlb|pci...
119
  	return (rec_cyc << 4) | 0x08 | act_cyc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
122
123
124
125
126
127
128
129
  }
  
  /*
   * qd6580_compute_timing
   *
   * idem for qd6580
   */
  
  static u8 qd6580_compute_timing (int active_time, int recovery_time)
  {
30e5ee4d1   Bartlomiej Zolnierkiewicz   ide: remove obsol...
130
  	int clk = ide_vlb_clk ? ide_vlb_clk : 50;
ebae41a5a   Bartlomiej Zolnierkiewicz   ide: add "vlb|pci...
131
  	u8 act_cyc, rec_cyc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132

ebae41a5a   Bartlomiej Zolnierkiewicz   ide: add "vlb|pci...
133
134
135
136
  	act_cyc = 17 - IDE_IN(active_time   * clk / 1000 + 1, 2, 17);
  	rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 2, 15);
  
  	return (rec_cyc << 4) | act_cyc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
139
140
141
142
143
144
145
146
147
148
  }
  
  /*
   * qd_find_disk_type
   *
   * tries to find timing from dos driver's table
   */
  
  static int qd_find_disk_type (ide_drive_t *drive,
  		int *active_time, int *recovery_time)
  {
  	struct qd65xx_timing_s *p;
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
149
150
  	char *m = (char *)&drive->id[ATA_ID_PROD];
  	char model[ATA_ID_PROD_LEN];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151

4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
152
153
  	if (*m == 0)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154

4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
155
156
  	strncpy(model, m, ATA_ID_PROD_LEN);
  	ide_fixstring(model, ATA_ID_PROD_LEN, 1); /* byte-swap */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
158
159
160
161
162
163
164
165
166
167
168
169
170
  
  	for (p = qd65xx_timing ; p->offset != -1 ; p++) {
  		if (!strncmp(p->model, model+p->offset, 4)) {
  			printk(KERN_DEBUG "%s: listed !
  ", drive->name);
  			*active_time = p->active;
  			*recovery_time = p->recovery;
  			return 1;
  		}
  	}
  	return 0;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
172
   * qd_set_timing:
   *
d07616f19   Bartlomiej Zolnierkiewicz   qd65xx: always us...
173
   * records the timing
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
176
177
   */
  
  static void qd_set_timing (ide_drive_t *drive, u8 timing)
  {
5bfb151f1   Joao Ramos   ide: do not acces...
178
179
180
181
182
  	unsigned long data = (unsigned long)ide_get_drivedata(drive);
  
  	data &= 0xff00;
  	data |= timing;
  	ide_set_drivedata(drive, (void *)data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
185
186
  
  	printk(KERN_DEBUG "%s: %#x
  ", drive->name, timing);
  }
e085b3cae   Bartlomiej Zolnierkiewicz   ide: change ->set...
187
  static void qd6500_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  {
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
189
  	u16 *id = drive->id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
191
  	int active_time   = 175;
  	int recovery_time = 415; /* worst case values from the dos driver */
e085b3cae   Bartlomiej Zolnierkiewicz   ide: change ->set...
192
  	/* FIXME: use drive->pio_mode value */
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
193
  	if (!qd_find_disk_type(drive, &active_time, &recovery_time) &&
48fb2688a   Bartlomiej Zolnierkiewicz   ide: remove drive...
194
  	    (id[ATA_ID_OLD_PIO_MODES] & 0xff) && (id[ATA_ID_FIELD_VALID] & 2) &&
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
195
  	    id[ATA_ID_EIDE_PIO] >= 240) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
  		printk(KERN_INFO "%s: PIO mode%d
  ", drive->name,
48fb2688a   Bartlomiej Zolnierkiewicz   ide: remove drive...
198
  			id[ATA_ID_OLD_PIO_MODES] & 0xff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
  		active_time = 110;
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
200
  		recovery_time = drive->id[ATA_ID_EIDE_PIO] - 120;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
  	}
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
202
203
  	qd_set_timing(drive, qd6500_compute_timing(drive->hwif,
  				active_time, recovery_time));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
  }
e085b3cae   Bartlomiej Zolnierkiewicz   ide: change ->set...
205
  static void qd6580_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
  {
e085b3cae   Bartlomiej Zolnierkiewicz   ide: change ->set...
207
  	const u8 pio = drive->pio_mode - XFER_PIO_0;
2feecface   Bartlomiej Zolnierkiewicz   qd65xx: convert t...
208
  	struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
7dd00083b   Bartlomiej Zolnierkiewicz   ide: add ide_pio_...
209
  	unsigned int cycle_time;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
  	int active_time   = 175;
  	int recovery_time = 415; /* worst case values from the dos driver */
79472b6ea   Bartlomiej Zolnierkiewicz   qd65xx: use IDE_H...
212
  	u8 base = (hwif->config_data & 0xff00) >> 8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
  
  	if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) {
7dd00083b   Bartlomiej Zolnierkiewicz   ide: add ide_pio_...
215
  		cycle_time = ide_pio_cycle_time(drive, pio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
219
  
  		switch (pio) {
  			case 0: break;
  			case 3:
7dd00083b   Bartlomiej Zolnierkiewicz   ide: add ide_pio_...
220
  				if (cycle_time >= 110) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  					active_time = 86;
7dd00083b   Bartlomiej Zolnierkiewicz   ide: add ide_pio_...
222
  					recovery_time = cycle_time - 102;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
224
225
226
227
  				} else
  					printk(KERN_WARNING "%s: Strange recovery time !
  ",drive->name);
  				break;
  			case 4:
7dd00083b   Bartlomiej Zolnierkiewicz   ide: add ide_pio_...
228
  				if (cycle_time >= 69) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
  					active_time = 70;
7dd00083b   Bartlomiej Zolnierkiewicz   ide: add ide_pio_...
230
  					recovery_time = cycle_time - 61;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
233
234
235
  				} else
  					printk(KERN_WARNING "%s: Strange recovery time !
  ",drive->name);
  				break;
  			default:
7dd00083b   Bartlomiej Zolnierkiewicz   ide: add ide_pio_...
236
  				if (cycle_time >= 180) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
  					active_time = 110;
7dd00083b   Bartlomiej Zolnierkiewicz   ide: add ide_pio_...
238
  					recovery_time = cycle_time - 120;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
  				} else {
2feecface   Bartlomiej Zolnierkiewicz   qd65xx: convert t...
240
  					active_time = t->active;
7dd00083b   Bartlomiej Zolnierkiewicz   ide: add ide_pio_...
241
  					recovery_time = cycle_time - active_time;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
244
245
246
  				}
  		}
  		printk(KERN_INFO "%s: PIO mode%d
  ", drive->name,pio);
  	}
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
247
  	if (!hwif->channel && drive->media != ide_disk) {
c196567a8   Bartlomiej Zolnierkiewicz   qd65xx: remove po...
248
  		outb(0x5f, QD_CONTROL_PORT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
  		printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO "
  			"and post-write buffer on %s.
  ",
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
252
  			drive->name, hwif->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
254
255
256
257
258
259
260
261
262
263
264
265
  	}
  
  	qd_set_timing(drive, qd6580_compute_timing(active_time, recovery_time));
  }
  
  /*
   * qd_testreg
   *
   * tests if the given port is a register
   */
  
  static int __init qd_testreg(int port)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
  	unsigned long flags;
f949820de   Bartlomiej Zolnierkiewicz   qd65xx: fix deadl...
267
  	u8 savereg, readreg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268

c196567a8   Bartlomiej Zolnierkiewicz   qd65xx: remove po...
269
  	local_irq_save(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
271
272
273
  	savereg = inb_p(port);
  	outb_p(QD_TESTVAL, port);	/* safe value */
  	readreg = inb_p(port);
  	outb(savereg, port);
c196567a8   Bartlomiej Zolnierkiewicz   qd65xx: remove po...
274
  	local_irq_restore(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
276
277
278
279
280
281
282
283
284
285
286
287
  
  	if (savereg == QD_TESTVAL) {
  		printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !
  ");
  		printk(KERN_ERR "Please contact maintainers to tell about your hardware
  ");
  		printk(KERN_ERR "Assuming qd65xx is not present.
  ");
  		return 1;
  	}
  
  	return (readreg != QD_TESTVAL);
  }
e6d95bd14   Bartlomiej Zolnierkiewicz   ide: ->port_init_...
288
  static void __init qd6500_init_dev(ide_drive_t *drive)
1f2cf8b00   Bartlomiej Zolnierkiewicz   ide: add ->port_i...
289
  {
e6d95bd14   Bartlomiej Zolnierkiewicz   ide: ->port_init_...
290
  	ide_hwif_t *hwif = drive->hwif;
79472b6ea   Bartlomiej Zolnierkiewicz   qd65xx: use IDE_H...
291
292
  	u8 base = (hwif->config_data & 0xff00) >> 8;
  	u8 config = QD_CONFIG(hwif);
1f2cf8b00   Bartlomiej Zolnierkiewicz   ide: add ->port_i...
293

5bfb151f1   Joao Ramos   ide: do not acces...
294
  	ide_set_drivedata(drive, (void *)QD6500_DEF_DATA);
1f2cf8b00   Bartlomiej Zolnierkiewicz   ide: add ->port_i...
295
  }
e6d95bd14   Bartlomiej Zolnierkiewicz   ide: ->port_init_...
296
  static void __init qd6580_init_dev(ide_drive_t *drive)
1f2cf8b00   Bartlomiej Zolnierkiewicz   ide: add ->port_i...
297
  {
e6d95bd14   Bartlomiej Zolnierkiewicz   ide: ->port_init_...
298
  	ide_hwif_t *hwif = drive->hwif;
1f2cf8b00   Bartlomiej Zolnierkiewicz   ide: add ->port_i...
299
  	u16 t1, t2;
79472b6ea   Bartlomiej Zolnierkiewicz   qd65xx: use IDE_H...
300
301
  	u8 base = (hwif->config_data & 0xff00) >> 8;
  	u8 config = QD_CONFIG(hwif);
1f2cf8b00   Bartlomiej Zolnierkiewicz   ide: add ->port_i...
302

79472b6ea   Bartlomiej Zolnierkiewicz   qd65xx: use IDE_H...
303
  	if (hwif->host_flags & IDE_HFLAG_SINGLE) {
1f2cf8b00   Bartlomiej Zolnierkiewicz   ide: add ->port_i...
304
305
306
307
  		t1 = QD6580_DEF_DATA;
  		t2 = QD6580_DEF_DATA2;
  	} else
  		t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA;
5bfb151f1   Joao Ramos   ide: do not acces...
308
  	ide_set_drivedata(drive, (void *)((drive->dn & 1) ? t2 : t1));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
  }
abb596b25   Sergei Shtylyov   ide: turn selectp...
310
311
312
313
314
315
316
317
318
319
320
321
322
  static const struct ide_tp_ops qd65xx_tp_ops = {
  	.exec_command		= ide_exec_command,
  	.read_status		= ide_read_status,
  	.read_altstatus		= ide_read_altstatus,
  	.write_devctl		= ide_write_devctl,
  
  	.dev_select		= qd65xx_dev_select,
  	.tf_load		= ide_tf_load,
  	.tf_read		= ide_tf_read,
  
  	.input_data		= ide_input_data,
  	.output_data		= ide_output_data,
  };
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
323
  static const struct ide_port_ops qd6500_port_ops = {
e6d95bd14   Bartlomiej Zolnierkiewicz   ide: ->port_init_...
324
  	.init_dev		= qd6500_init_dev,
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
325
  	.set_pio_mode		= qd6500_set_pio_mode,
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
326
327
328
  };
  
  static const struct ide_port_ops qd6580_port_ops = {
e6d95bd14   Bartlomiej Zolnierkiewicz   ide: ->port_init_...
329
  	.init_dev		= qd6580_init_dev,
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
330
  	.set_pio_mode		= qd6580_set_pio_mode,
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
331
  };
c413b9b94   Bartlomiej Zolnierkiewicz   ide: add struct i...
332
  static const struct ide_port_info qd65xx_port_info __initdata = {
d92f1a282   Bartlomiej Zolnierkiewicz   ide: manage I/O r...
333
  	.name			= DRV_NAME,
abb596b25   Sergei Shtylyov   ide: turn selectp...
334
  	.tp_ops 		= &qd65xx_tp_ops,
c413b9b94   Bartlomiej Zolnierkiewicz   ide: add struct i...
335
336
  	.chipset		= ide_qd65xx,
  	.host_flags		= IDE_HFLAG_IO_32BIT |
0d28ec7f2   Bartlomiej Zolnierkiewicz   ide: always auto-...
337
  				  IDE_HFLAG_NO_DMA,
c413b9b94   Bartlomiej Zolnierkiewicz   ide: add struct i...
338
339
  	.pio_mask		= ATA_PIO4,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
341
342
343
344
345
346
347
348
  /*
   * qd_probe:
   *
   * looks at the specified baseport, and if qd found, registers & initialises it
   * return 1 if another qd may be probed
   */
  
  static int __init qd_probe(int base)
  {
0bfeee7d4   Bartlomiej Zolnierkiewicz   ide: use ide_lega...
349
  	int rc;
7a2199f34   Bartlomiej Zolnierkiewicz   qd65xx: cleanup q...
350
  	u8 config, unit, control;
e277f91fe   Bartlomiej Zolnierkiewicz   ide: use ide_find...
351
  	struct ide_port_info d = qd65xx_port_info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352

c196567a8   Bartlomiej Zolnierkiewicz   qd65xx: remove po...
353
  	config = inb(QD_CONFIG_PORT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
355
  
  	if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) )
7daf66dd1   Bartlomiej Zolnierkiewicz   qd65xx: return er...
356
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
358
  
  	unit = ! (config & QD_CONFIG_IDE_BASEPORT);
e277f91fe   Bartlomiej Zolnierkiewicz   ide: use ide_find...
359
360
  	if (unit)
  		d.host_flags |= IDE_HFLAG_QD_2ND_PORT;
7a2199f34   Bartlomiej Zolnierkiewicz   qd65xx: cleanup q...
361
362
  	switch (config & 0xf0) {
  	case QD_CONFIG_QD6500:
7daf66dd1   Bartlomiej Zolnierkiewicz   qd65xx: return er...
363
364
  		if (qd_testreg(base))
  			 return -ENODEV;	/* bad register */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
367
368
  		if (config & QD_CONFIG_DISABLED) {
  			printk(KERN_WARNING "qd6500 is disabled !
  ");
7daf66dd1   Bartlomiej Zolnierkiewicz   qd65xx: return er...
369
  			return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
  		}
e277f91fe   Bartlomiej Zolnierkiewicz   ide: use ide_find...
371
372
373
374
375
  		printk(KERN_NOTICE "qd6500 at %#x
  ", base);
  		printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u
  ",
  			config, QD_ID3);
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
376
  		d.port_ops = &qd6500_port_ops;
79472b6ea   Bartlomiej Zolnierkiewicz   qd65xx: use IDE_H...
377
  		d.host_flags |= IDE_HFLAG_SINGLE;
7a2199f34   Bartlomiej Zolnierkiewicz   qd65xx: cleanup q...
378
379
380
  		break;
  	case QD_CONFIG_QD6580_A:
  	case QD_CONFIG_QD6580_B:
7daf66dd1   Bartlomiej Zolnierkiewicz   qd65xx: return er...
381
382
  		if (qd_testreg(base) || qd_testreg(base + 0x02))
  			return -ENODEV;	/* bad registers */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383

c196567a8   Bartlomiej Zolnierkiewicz   qd65xx: remove po...
384
  		control = inb(QD_CONTROL_PORT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
386
387
388
389
390
  
  		printk(KERN_NOTICE "qd6580 at %#x
  ", base);
  		printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u
  ",
  			config, control, QD_ID3);
788d66973   Bartlomiej Zolnierkiewicz   qd65xx: fix setup...
391
  		outb(QD_DEF_CONTR, QD_CONTROL_PORT);
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
392
  		d.port_ops = &qd6580_port_ops;
7a2199f34   Bartlomiej Zolnierkiewicz   qd65xx: cleanup q...
393
  		if (control & QD_CONTR_SEC_DISABLED)
79472b6ea   Bartlomiej Zolnierkiewicz   qd65xx: use IDE_H...
394
  			d.host_flags |= IDE_HFLAG_SINGLE;
7a2199f34   Bartlomiej Zolnierkiewicz   qd65xx: cleanup q...
395
396
397
398
399
400
401
  		printk(KERN_INFO "qd6580: %s IDE board
  ",
  			(control & QD_CONTR_SEC_DISABLED) ? "single" : "dual");
  		break;
  	default:
  		return -ENODEV;
  	}
26bcb879c   Bartlomiej Zolnierkiewicz   ide: add ide_set{...
402

7a2199f34   Bartlomiej Zolnierkiewicz   qd65xx: cleanup q...
403
  	rc = ide_legacy_device_add(&d, (base << 8) | config);
e277f91fe   Bartlomiej Zolnierkiewicz   ide: use ide_find...
404

7a2199f34   Bartlomiej Zolnierkiewicz   qd65xx: cleanup q...
405
406
  	if (d.host_flags & IDE_HFLAG_SINGLE)
  		return (rc == 0) ? 1 : rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407

7a2199f34   Bartlomiej Zolnierkiewicz   qd65xx: cleanup q...
408
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
  }
ef87f8d09   Bartlomiej Zolnierkiewicz   ide: remove obsol...
410
  static int probe_qd65xx;
849138827   Bartlomiej Zolnierkiewicz   ide: make legacy ...
411
412
413
  
  module_param_named(probe, probe_qd65xx, bool, 0);
  MODULE_PARM_DESC(probe, "probe for QD65xx chipsets");
ade2daf9c   Bartlomiej Zolnierkiewicz   ide: make remaini...
414
  static int __init qd65xx_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
  {
7daf66dd1   Bartlomiej Zolnierkiewicz   qd65xx: return er...
416
  	int rc1, rc2 = -ENODEV;
849138827   Bartlomiej Zolnierkiewicz   ide: make legacy ...
417
418
  	if (probe_qd65xx == 0)
  		return -ENODEV;
7daf66dd1   Bartlomiej Zolnierkiewicz   qd65xx: return er...
419
420
421
422
423
  	rc1 = qd_probe(0x30);
  	if (rc1)
  		rc2 = qd_probe(0xb0);
  
  	if (rc1 < 0 && rc2 < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
  		return -ENODEV;
7daf66dd1   Bartlomiej Zolnierkiewicz   qd65xx: return er...
425

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
427
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
  module_init(qd65xx_init);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
430
431
432
  
  MODULE_AUTHOR("Samuel Thibault");
  MODULE_DESCRIPTION("support of qd65xx vlb ide chipset");
  MODULE_LICENSE("GPL");