Blame view

drivers/ide/setup-pci.c 16.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
59bca8cc9   Bartlomiej Zolnierkiewicz   ide: update/add m...
2
3
   *  Copyright (C) 1998-2000  Andre Hedrick <andre@linux-ide.org>
   *  Copyright (C) 1995-1998  Mark Lord
ad7c52d09   Bartlomiej Zolnierkiewicz   ide: re-implement...
4
   *  Copyright (C) 2007-2009  Bartlomiej Zolnierkiewicz
58f189fcc   Bartlomiej Zolnierkiewicz   ide: delete filen...
5
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
   *  May be copied or modified under the terms of the GNU General Public License
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
  #include <linux/types.h>
  #include <linux/kernel.h>
  #include <linux/pci.h>
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
  #include <linux/interrupt.h>
  #include <linux/ide.h>
  #include <linux/dma-mapping.h>
  
  #include <asm/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
23
24
  /**
   *	ide_setup_pci_baseregs	-	place a PCI IDE controller native
   *	@dev: PCI device of interface to switch native
   *	@name: Name of interface
   *
   *	We attempt to place the PCI interface into PCI native mode. If
   *	we succeed the BARs are ok and the controller is in PCI mode.
846bb88ae   Paolo Ciarrocchi   IDE: Coding Style...
25
   *	Returns 0 on success or an errno code.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
   *
   *	FIXME: if we program the interface and then fail to set the BARS
   *	we don't switch it back to legacy mode. Do we actually care ??
   */
846bb88ae   Paolo Ciarrocchi   IDE: Coding Style...
30
31
  
  static int ide_setup_pci_baseregs(struct pci_dev *dev, const char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
35
36
37
38
39
40
  {
  	u8 progif = 0;
  
  	/*
  	 * Place both IDE interfaces into PCI "native" mode:
  	 */
  	if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||
  			 (progif & 5) != 5) {
  		if ((progif & 0xa) != 0xa) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
41
42
43
  			printk(KERN_INFO "%s %s: device not capable of full "
  				"native PCI mode
  ", name, pci_name(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
  			return -EOPNOTSUPP;
  		}
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
46
47
48
  		printk(KERN_INFO "%s %s: placing both ports into native PCI "
  			"mode
  ", name, pci_name(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
  		(void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);
  		if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||
  		    (progif & 5) != 5) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
52
53
54
55
  			printk(KERN_ERR "%s %s: rewrite of PROGIF failed, "
  				"wanted 0x%04x, got 0x%04x
  ",
  				name, pci_name(dev), progif | 5, progif);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
59
60
61
62
  			return -EOPNOTSUPP;
  		}
  	}
  	return 0;
  }
  
  #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
63
  static int ide_pci_clear_simplex(unsigned long dma_base, const char *name)
8ac2b42a4   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
64
65
66
67
68
  {
  	u8 dma_stat = inb(dma_base + 2);
  
  	outb(dma_stat & 0x60, dma_base + 2);
  	dma_stat = inb(dma_base + 2);
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
69
70
  
  	return (dma_stat & 0x80) ? 1 : 0;
8ac2b42a4   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
71
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
  /**
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
73
   *	ide_pci_dma_base	-	setup BMIBA
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
74
   *	@hwif: IDE interface
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
75
   *	@d: IDE port info
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
   *
c58e79dd4   Bartlomiej Zolnierkiewicz   ide: remove CONFI...
77
   *	Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
   */
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
79
  unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
  {
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
81
82
  	struct pci_dev *dev = to_pci_dev(hwif->dev);
  	unsigned long dma_base = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83

135721446   Bartlomiej Zolnierkiewicz   ide: remove ->mmi...
84
  	if (hwif->host_flags & IDE_HFLAG_MMIO)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
87
88
89
  		return hwif->dma_base;
  
  	if (hwif->mate && hwif->mate->dma_base) {
  		dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
  	} else {
9ffcf364f   Bartlomiej Zolnierkiewicz   ide: remove ->ini...
90
91
92
  		u8 baridx = (d->host_flags & IDE_HFLAG_CS5520) ? 2 : 4;
  
  		dma_base = pci_resource_start(dev, baridx);
aea5d3756   Bartlomiej Zolnierkiewicz   ide: (hopefully) ...
93
  		if (dma_base == 0) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
94
95
96
  			printk(KERN_ERR "%s %s: DMA base is invalid
  ",
  				d->name, pci_name(dev));
aea5d3756   Bartlomiej Zolnierkiewicz   ide: (hopefully) ...
97
98
  			return 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
  	}
aea5d3756   Bartlomiej Zolnierkiewicz   ide: (hopefully) ...
100
101
  	if (hwif->channel)
  		dma_base += 8;
ebb00fb55   Bartlomiej Zolnierkiewicz   ide: factor out s...
102
103
104
105
106
107
  	return dma_base;
  }
  EXPORT_SYMBOL_GPL(ide_pci_dma_base);
  
  int ide_pci_check_simplex(ide_hwif_t *hwif, const struct ide_port_info *d)
  {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
108
  	struct pci_dev *dev = to_pci_dev(hwif->dev);
ebb00fb55   Bartlomiej Zolnierkiewicz   ide: factor out s...
109
110
111
  	u8 dma_stat;
  
  	if (d->host_flags & (IDE_HFLAG_MMIO | IDE_HFLAG_CS5520))
8ac2b42a4   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
112
113
114
  		goto out;
  
  	if (d->host_flags & IDE_HFLAG_CLEAR_SIMPLEX) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
115
116
117
118
  		if (ide_pci_clear_simplex(hwif->dma_base, d->name))
  			printk(KERN_INFO "%s %s: simplex device: DMA forced
  ",
  				d->name, pci_name(dev));
8ac2b42a4   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
119
120
121
122
123
124
125
126
127
128
129
130
131
  		goto out;
  	}
  
  	/*
  	 * If the device claims "simplex" DMA, this means that only one of
  	 * the two interfaces can be trusted with DMA at any point in time
  	 * (so we should enable DMA only on one of the two interfaces).
  	 *
  	 * FIXME: At this point we haven't probed the drives so we can't make
  	 * the appropriate decision.  Really we should defer this problem until
  	 * we tune the drive then try to grab DMA ownership if we want to be
  	 * the DMA end.  This has to be become dynamic to handle hot-plug.
  	 */
592b53152   Sergei Shtylyov   ide: move read_sf...
132
  	dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
8ac2b42a4   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
133
  	if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
134
135
136
  		printk(KERN_INFO "%s %s: simplex device: DMA disabled
  ",
  			d->name, pci_name(dev));
ebb00fb55   Bartlomiej Zolnierkiewicz   ide: factor out s...
137
  		return -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
  	}
8ac2b42a4   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
139
  out:
ebb00fb55   Bartlomiej Zolnierkiewicz   ide: factor out s...
140
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  }
ebb00fb55   Bartlomiej Zolnierkiewicz   ide: factor out s...
142
  EXPORT_SYMBOL_GPL(ide_pci_check_simplex);
d54452fbf   Bartlomiej Zolnierkiewicz   ide: factor out s...
143
144
145
146
  
  /*
   * Set up BM-DMA capability (PnP BIOS should have done this)
   */
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
147
  int ide_pci_set_master(struct pci_dev *dev, const char *name)
d54452fbf   Bartlomiej Zolnierkiewicz   ide: factor out s...
148
149
150
151
152
153
154
155
156
157
  {
  	u16 pcicmd;
  
  	pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
  
  	if ((pcicmd & PCI_COMMAND_MASTER) == 0) {
  		pci_set_master(dev);
  
  		if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) ||
  		    (pcicmd & PCI_COMMAND_MASTER) == 0) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
158
159
160
  			printk(KERN_ERR "%s %s: error updating PCICMD
  ",
  				name, pci_name(dev));
d54452fbf   Bartlomiej Zolnierkiewicz   ide: factor out s...
161
162
163
164
165
166
  			return -EIO;
  		}
  	}
  
  	return 0;
  }
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
167
  EXPORT_SYMBOL_GPL(ide_pci_set_master);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
  #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
856204360   Bartlomiej Zolnierkiewicz   ide: constify str...
169
  void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
171
172
173
174
  	printk(KERN_INFO "%s %s: IDE controller (0x%04x:0x%04x rev 0x%02x)
  ",
  		d->name, pci_name(dev),
  		dev->vendor, dev->device, dev->revision);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
179
180
181
  EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
  
  
  /**
   *	ide_pci_enable	-	do PCI enables
   *	@dev: PCI device
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
182
   *	@d: IDE port info
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
   *
   *	Enable the IDE PCI device. We attempt to enable the device in full
094839164   Benjamin Herrenschmidt   PCI: Remove users...
185
186
187
   *	but if that fails then we only need IO space. The PCI code should
   *	have setup the proper resources for us already for controllers in
   *	legacy mode.
846bb88ae   Paolo Ciarrocchi   IDE: Coding Style...
188
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
   *	Returns zero on success or an error code
   */
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
191

856204360   Bartlomiej Zolnierkiewicz   ide: constify str...
192
  static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
  {
0d1bad216   Bartlomiej Zolnierkiewicz   ide: manage resou...
194
  	int ret, bars;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
  
  	if (pci_enable_device(dev)) {
094839164   Benjamin Herrenschmidt   PCI: Remove users...
197
  		ret = pci_enable_device_io(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  		if (ret < 0) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
199
200
201
  			printk(KERN_WARNING "%s %s: couldn't enable device
  ",
  				d->name, pci_name(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
  			goto out;
  		}
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
204
205
206
  		printk(KERN_WARNING "%s %s: BIOS configuration fixed
  ",
  			d->name, pci_name(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
208
209
  	}
  
  	/*
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
210
211
212
  	 * assume all devices can do 32-bit DMA for now, we can add
  	 * a DMA mask field to the struct ide_port_info if we need it
  	 * (or let lower level driver set the DMA mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
  	 */
284901a90   Yang Hongyang   dma-mapping: repl...
214
  	ret = pci_set_dma_mask(dev, DMA_BIT_MASK(32));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
  	if (ret < 0) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
216
217
218
  		printk(KERN_ERR "%s %s: can't set DMA mask
  ",
  			d->name, pci_name(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
  		goto out;
  	}
0d1bad216   Bartlomiej Zolnierkiewicz   ide: manage resou...
221
222
223
224
  	if (d->host_flags & IDE_HFLAG_SINGLE)
  		bars = (1 << 2) - 1;
  	else
  		bars = (1 << 4) - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225

0d1bad216   Bartlomiej Zolnierkiewicz   ide: manage resou...
226
227
228
229
230
231
232
233
234
  	if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) {
  		if (d->host_flags & IDE_HFLAG_CS5520)
  			bars |= (1 << 2);
  		else
  			bars |= (1 << 4);
  	}
  
  	ret = pci_request_selected_regions(dev, bars, d->name);
  	if (ret < 0)
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
235
236
237
  		printk(KERN_ERR "%s %s: can't reserve resources
  ",
  			d->name, pci_name(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
240
241
242
243
244
  out:
  	return ret;
  }
  
  /**
   *	ide_pci_configure	-	configure an unconfigured device
   *	@dev: PCI device
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
245
   *	@d: IDE port info
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
247
248
249
   *
   *	Enable and configure the PCI device we have been passed.
   *	Returns zero on success or an error code.
   */
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
250

856204360   Bartlomiej Zolnierkiewicz   ide: constify str...
251
  static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
253
254
255
256
257
258
259
260
  {
  	u16 pcicmd = 0;
  	/*
  	 * PnP BIOS was *supposed* to have setup this device, but we
  	 * can do it ourselves, so long as the BIOS has assigned an IRQ
  	 * (or possibly the device is using a "legacy header" for IRQs).
  	 * Maybe the user deliberately *disabled* the device,
  	 * but we'll eventually ignore it again if no drives respond.
  	 */
846bb88ae   Paolo Ciarrocchi   IDE: Coding Style...
261
262
  	if (ide_setup_pci_baseregs(dev, d->name) ||
  	    pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
263
264
265
  		printk(KERN_INFO "%s %s: device disabled (BIOS)
  ",
  			d->name, pci_name(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
268
  		return -ENODEV;
  	}
  	if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
269
270
271
  		printk(KERN_ERR "%s %s: error accessing PCI regs
  ",
  			d->name, pci_name(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
273
274
  		return -EIO;
  	}
  	if (!(pcicmd & PCI_COMMAND_IO)) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
275
276
277
  		printk(KERN_ERR "%s %s: unable to enable IDE controller
  ",
  			d->name, pci_name(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
279
280
281
282
283
284
  		return -ENXIO;
  	}
  	return 0;
  }
  
  /**
   *	ide_pci_check_iomem	-	check a register is I/O
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
285
286
287
   *	@dev: PCI device
   *	@d: IDE port info
   *	@bar: BAR number
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
   *
1baccff8a   Sergei Shtylyov   ide: make ide_pci...
289
290
   *	Checks if a BAR is configured and points to MMIO space. If so,
   *	return an error code. Otherwise return 0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
   */
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
292

1baccff8a   Sergei Shtylyov   ide: make ide_pci...
293
294
  static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *d,
  			       int bar)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
296
  {
  	ulong flags = pci_resource_flags(dev, bar);
846bb88ae   Paolo Ciarrocchi   IDE: Coding Style...
297

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
299
300
  	/* Unconfigured ? */
  	if (!flags || pci_resource_len(dev, bar) == 0)
  		return 0;
1baccff8a   Sergei Shtylyov   ide: make ide_pci...
301
302
  	/* I/O space */
  	if (flags & IORESOURCE_IO)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
  		return 0;
846bb88ae   Paolo Ciarrocchi   IDE: Coding Style...
304

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
  	/* Bad */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
307
308
309
  	return -EINVAL;
  }
  
  /**
9f36d3143   Bartlomiej Zolnierkiewicz   ide: remove hw_re...
310
   *	ide_hw_configure	-	configure a struct ide_hw instance
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
   *	@dev: PCI device holding interface
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
312
   *	@d: IDE port info
1ebf74936   Bartlomiej Zolnierkiewicz   ide: separate PCI...
313
   *	@port: port number
9f36d3143   Bartlomiej Zolnierkiewicz   ide: remove hw_re...
314
   *	@hw: struct ide_hw instance corresponding to this port
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
316
317
318
319
   *
   *	Perform the initial set up for the hardware interface structure. This
   *	is done per interface port rather than per PCI device. There may be
   *	more than one port per device.
   *
48c3c1072   Bartlomiej Zolnierkiewicz   ide: add struct i...
320
   *	Returns zero on success or an error code.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
   */
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
322

48c3c1072   Bartlomiej Zolnierkiewicz   ide: add struct i...
323
  static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d,
9f36d3143   Bartlomiej Zolnierkiewicz   ide: remove hw_re...
324
  			    unsigned int port, struct ide_hw *hw)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
  {
  	unsigned long ctl = 0, base = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327

a5d8c5c83   Bartlomiej Zolnierkiewicz   ide: add ide_pci_...
328
  	if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) {
1baccff8a   Sergei Shtylyov   ide: make ide_pci...
329
330
  		if (ide_pci_check_iomem(dev, d, 2 * port) ||
  		    ide_pci_check_iomem(dev, d, 2 * port + 1)) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
331
332
333
334
  			printk(KERN_ERR "%s %s: I/O baseregs (BIOS) are "
  				"reported as MEM for port %d!
  ",
  				d->name, pci_name(dev), port);
48c3c1072   Bartlomiej Zolnierkiewicz   ide: add struct i...
335
  			return -EINVAL;
1baccff8a   Sergei Shtylyov   ide: make ide_pci...
336
  		}
846bb88ae   Paolo Ciarrocchi   IDE: Coding Style...
337

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
339
  		ctl  = pci_resource_start(dev, 2*port+1);
  		base = pci_resource_start(dev, 2*port);
c1da678b5   Bartlomiej Zolnierkiewicz   ide: tighten chec...
340
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
343
344
  		/* Use default values */
  		ctl = port ? 0x374 : 0x3f4;
  		base = port ? 0x170 : 0x1f0;
  	}
bad7c825c   Bartlomiej Zolnierkiewicz   ide: cleanup ide_...
345

c1da678b5   Bartlomiej Zolnierkiewicz   ide: tighten chec...
346
  	if (!base || !ctl) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
347
348
349
  		printk(KERN_ERR "%s %s: bad PCI BARs for port %d, skipping
  ",
  			d->name, pci_name(dev), port);
48c3c1072   Bartlomiej Zolnierkiewicz   ide: add struct i...
350
  		return -EINVAL;
c1da678b5   Bartlomiej Zolnierkiewicz   ide: tighten chec...
351
  	}
c97c6aca7   Bartlomiej Zolnierkiewicz   ide: pass hw_regs...
352
  	memset(hw, 0, sizeof(*hw));
c97c6aca7   Bartlomiej Zolnierkiewicz   ide: pass hw_regs...
353
  	hw->dev = &dev->dev;
c97c6aca7   Bartlomiej Zolnierkiewicz   ide: pass hw_regs...
354
  	ide_std_init_ports(hw, base, ctl | 2);
48c3c1072   Bartlomiej Zolnierkiewicz   ide: add struct i...
355
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
  }
c413b9b94   Bartlomiej Zolnierkiewicz   ide: add struct i...
357
  #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
359
  /**
   *	ide_hwif_setup_dma	-	configure DMA interface
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
360
   *	@hwif: IDE interface
c413b9b94   Bartlomiej Zolnierkiewicz   ide: add struct i...
361
   *	@d: IDE port info
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
364
365
366
   *
   *	Set up the DMA base for the interface. Enable the master bits as
   *	necessary and attempt to bring the device DMA into a ready to use
   *	state
   */
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
367

b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
368
  int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
  {
c413b9b94   Bartlomiej Zolnierkiewicz   ide: add struct i...
370
  	struct pci_dev *dev = to_pci_dev(hwif->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371

47b687882   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
372
  	if ((d->host_flags & IDE_HFLAG_NO_AUTODMA) == 0 ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
374
  	    ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
  	     (dev->class & 0x80))) {
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
375
  		unsigned long base = ide_pci_dma_base(hwif, d);
d54452fbf   Bartlomiej Zolnierkiewicz   ide: factor out s...
376

ebb00fb55   Bartlomiej Zolnierkiewicz   ide: factor out s...
377
378
379
380
  		if (base == 0)
  			return -1;
  
  		hwif->dma_base = base;
592b53152   Sergei Shtylyov   ide: move read_sf...
381
382
  		if (hwif->dma_ops == NULL)
  			hwif->dma_ops = &sff_dma_ops;
ebb00fb55   Bartlomiej Zolnierkiewicz   ide: factor out s...
383
384
385
386
  		if (ide_pci_check_simplex(hwif, d) < 0)
  			return -1;
  
  		if (ide_pci_set_master(dev, d->name) < 0)
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
387
  			return -1;
d54452fbf   Bartlomiej Zolnierkiewicz   ide: factor out s...
388

135721446   Bartlomiej Zolnierkiewicz   ide: remove ->mmi...
389
  		if (hwif->host_flags & IDE_HFLAG_MMIO)
63158d5c2   Bartlomiej Zolnierkiewicz   ide: cleanup ide_...
390
391
392
393
394
395
396
397
  			printk(KERN_INFO "    %s: MMIO-DMA
  ", hwif->name);
  		else
  			printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx
  ",
  					 hwif->name, base, base + 7);
  
  		hwif->extra_base = base + (hwif->channel ? 8 : 16);
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
398
399
  		if (ide_allocate_dma_engine(hwif))
  			return -1;
b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
400
  	}
d54452fbf   Bartlomiej Zolnierkiewicz   ide: factor out s...
401

b123f56e0   Bartlomiej Zolnierkiewicz   ide: do complete ...
402
  	return 0;
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
403
  }
c413b9b94   Bartlomiej Zolnierkiewicz   ide: add struct i...
404
  #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
406
407
408
  
  /**
   *	ide_setup_pci_controller	-	set up IDE PCI
   *	@dev: PCI device
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
409
   *	@d: IDE port info
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
   *	@noisy: verbose flag
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
412
413
414
415
   *
   *	Set up the PCI and controller side of the IDE interface. This brings
   *	up the PCI side of the device, checks that the device is enabled
   *	and enables it if need be
   */
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
416

a95925a30   Bartlomiej Zolnierkiewicz   ide: respect dev-...
417
418
  static int ide_setup_pci_controller(struct pci_dev *dev,
  				    const struct ide_port_info *d, int noisy)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
420
  {
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
422
423
424
425
426
427
428
429
430
431
  	u16 pcicmd;
  
  	if (noisy)
  		ide_setup_pci_noise(dev, d);
  
  	ret = ide_pci_enable(dev, d);
  	if (ret < 0)
  		goto out;
  
  	ret = pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
  	if (ret < 0) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
432
433
434
  		printk(KERN_ERR "%s %s: error accessing PCI regs
  ",
  			d->name, pci_name(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
436
437
438
439
440
  		goto out;
  	}
  	if (!(pcicmd & PCI_COMMAND_IO)) {	/* is device disabled? */
  		ret = ide_pci_configure(dev, d);
  		if (ret < 0)
  			goto out;
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
441
442
443
  		printk(KERN_INFO "%s %s: device enabled (Linux)
  ",
  			d->name, pci_name(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
446
447
448
449
450
451
  out:
  	return ret;
  }
  
  /**
   *	ide_pci_setup_ports	-	configure ports/devices on PCI IDE
   *	@dev: PCI device
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
452
   *	@d: IDE port info
9f36d3143   Bartlomiej Zolnierkiewicz   ide: remove hw_re...
453
454
   *	@hw: struct ide_hw instances corresponding to this PCI IDE device
   *	@hws: struct ide_hw pointers table to update
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
456
457
458
459
460
461
462
463
   *
   *	Scan the interfaces attached to this device and do any
   *	necessary per port setup. Attach the devices and ask the
   *	generic DMA layer to do its work for us.
   *
   *	Normally called automaticall from do_ide_pci_setup_device,
   *	but is also used directly as a helper function by some controllers
   *	where the chipset setup is not the default PCI IDE one.
   */
8447d9d52   Bartlomiej Zolnierkiewicz   ide: add ide_devi...
464

c97c6aca7   Bartlomiej Zolnierkiewicz   ide: pass hw_regs...
465
  void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d,
9f36d3143   Bartlomiej Zolnierkiewicz   ide: remove hw_re...
466
  			 struct ide_hw *hw, struct ide_hw **hws)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
  {
a5d8c5c83   Bartlomiej Zolnierkiewicz   ide: add ide_pci_...
468
  	int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  	u8 tmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
471
472
  	/*
  	 * Set up the IDE ports
  	 */
cf6e854ef   Bartlomiej Zolnierkiewicz   ide: fix disabled...
473

a5d8c5c83   Bartlomiej Zolnierkiewicz   ide: add ide_pci_...
474
  	for (port = 0; port < channels; ++port) {
c0ae50234   Bartlomiej Zolnierkiewicz   ide: remove ide_p...
475
  		const struct ide_pci_enablebit *e = &d->enablebits[port];
856204360   Bartlomiej Zolnierkiewicz   ide: constify str...
476

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
  		if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) ||
cf6e854ef   Bartlomiej Zolnierkiewicz   ide: fix disabled...
478
  		    (tmp & e->mask) != e->val)) {
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
479
480
481
  			printk(KERN_INFO "%s %s: IDE port disabled
  ",
  				d->name, pci_name(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
  			continue;	/* port not enabled */
cf6e854ef   Bartlomiej Zolnierkiewicz   ide: fix disabled...
483
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484

86ccf37c6   Bartlomiej Zolnierkiewicz   ide: remove pciir...
485
  		if (ide_hw_configure(dev, d, port, hw + port))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
  			continue;
c97c6aca7   Bartlomiej Zolnierkiewicz   ide: pass hw_regs...
487
  		*(hws + port) = hw + port;
1ebf74936   Bartlomiej Zolnierkiewicz   ide: separate PCI...
488
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
491
492
493
494
495
496
497
498
  EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
  
  /*
   * ide_setup_pci_device() looks at the primary/secondary interfaces
   * on a PCI IDE device and, if they are enabled, prepares the IDE driver
   * for use with them.  This generic code works for most PCI chipsets.
   *
   * One thing that is not standardized is the location of the
   * primary/secondary interface "enable/disable" bits.  For chipsets that
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
499
   * we "know" about, this information is in the struct ide_port_info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
   * for all other chipsets, we just assume both interfaces are enabled.
   */
039788e15   Bartlomiej Zolnierkiewicz   ide: replace ide_...
502
  static int do_ide_setup_pci_device(struct pci_dev *dev,
856204360   Bartlomiej Zolnierkiewicz   ide: constify str...
503
  				   const struct ide_port_info *d,
51d87ed0a   Bartlomiej Zolnierkiewicz   ide: move ide_pci...
504
  				   u8 noisy)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
  	int pciirq, ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
507
508
509
510
  	/*
  	 * Can we trust the reported IRQ?
  	 */
  	pciirq = dev->irq;
708e5f9eb   Bartlomiej Zolnierkiewicz   ide: always call ...
511
512
513
514
515
516
  	/*
  	 * This allows offboard ide-pci cards the enable a BIOS,
  	 * verify interrupt settings of split-mirror pci-config
  	 * space, place chipset into init-mode, and/or preserve
  	 * an interrupt if the card is not native ide support.
  	 */
a326b02b0   Bartlomiej Zolnierkiewicz   ide: drop 'name' ...
517
  	ret = d->init_chipset ? d->init_chipset(dev) : 0;
708e5f9eb   Bartlomiej Zolnierkiewicz   ide: always call ...
518
519
  	if (ret < 0)
  		goto out;
8c6de94cf   Bartlomiej Zolnierkiewicz   ide: use ide_pci_...
520
  	if (ide_pci_is_in_compatibility_mode(dev)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
  		if (noisy)
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
522
523
524
  			printk(KERN_INFO "%s %s: not 100%% native mode: will "
  				"probe irqs later
  ", d->name, pci_name(dev));
2ed0ef543   Bartlomiej Zolnierkiewicz   ide: fix ->init_c...
525
  		pciirq = 0;
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
526
527
528
529
530
531
532
533
  	} else if (!pciirq && noisy) {
  		printk(KERN_WARNING "%s %s: bad irq (%d): will probe later
  ",
  			d->name, pci_name(dev), pciirq);
  	} else if (noisy) {
  		printk(KERN_INFO "%s %s: 100%% native mode on irq %d
  ",
  			d->name, pci_name(dev), pciirq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
  	}
51d87ed0a   Bartlomiej Zolnierkiewicz   ide: move ide_pci...
535
  	ret = pciirq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
537
538
  out:
  	return ret;
  }
6cdf6eb35   Bartlomiej Zolnierkiewicz   ide: add ->dev an...
539
540
  int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2,
  		     const struct ide_port_info *d, void *priv)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
  {
  	struct pci_dev *pdev[] = { dev1, dev2 };
6cdf6eb35   Bartlomiej Zolnierkiewicz   ide: add ->dev an...
543
  	struct ide_host *host;
ad7c52d09   Bartlomiej Zolnierkiewicz   ide: re-implement...
544
  	int ret, i, n_ports = dev2 ? 4 : 2;
9f36d3143   Bartlomiej Zolnierkiewicz   ide: remove hw_re...
545
  	struct ide_hw hw[4], *hws[] = { NULL, NULL, NULL, NULL };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546

ad7c52d09   Bartlomiej Zolnierkiewicz   ide: re-implement...
547
  	for (i = 0; i < n_ports / 2; i++) {
a742d6cf0   Bartlomiej Zolnierkiewicz   ide: move ide_set...
548
549
550
  		ret = ide_setup_pci_controller(pdev[i], d, !i);
  		if (ret < 0)
  			goto out;
86ccf37c6   Bartlomiej Zolnierkiewicz   ide: remove pciir...
551
  		ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]);
6cdf6eb35   Bartlomiej Zolnierkiewicz   ide: add ->dev an...
552
  	}
8c2eece50   Bartlomiej Zolnierkiewicz   ide: call ide_pci...
553

ad7c52d09   Bartlomiej Zolnierkiewicz   ide: re-implement...
554
  	host = ide_host_alloc(d, hws, n_ports);
6cdf6eb35   Bartlomiej Zolnierkiewicz   ide: add ->dev an...
555
556
557
558
559
560
  	if (host == NULL) {
  		ret = -ENOMEM;
  		goto out;
  	}
  
  	host->dev[0] = &dev1->dev;
ad7c52d09   Bartlomiej Zolnierkiewicz   ide: re-implement...
561
562
  	if (dev2)
  		host->dev[1] = &dev2->dev;
6cdf6eb35   Bartlomiej Zolnierkiewicz   ide: add ->dev an...
563
564
  
  	host->host_priv = priv;
255115fb3   Bartlomiej Zolnierkiewicz   ide: allow host d...
565
  	host->irq_flags = IRQF_SHARED;
ef0b04276   Bartlomiej Zolnierkiewicz   ide: add ide_pci_...
566
  	pci_set_drvdata(pdev[0], host);
ad7c52d09   Bartlomiej Zolnierkiewicz   ide: re-implement...
567
568
  	if (dev2)
  		pci_set_drvdata(pdev[1], host);
6cdf6eb35   Bartlomiej Zolnierkiewicz   ide: add ->dev an...
569

ad7c52d09   Bartlomiej Zolnierkiewicz   ide: re-implement...
570
  	for (i = 0; i < n_ports / 2; i++) {
51d87ed0a   Bartlomiej Zolnierkiewicz   ide: move ide_pci...
571
  		ret = do_ide_setup_pci_device(pdev[i], d, !i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572
573
574
575
576
577
  		/*
  		 * FIXME: Mom, mom, they stole me the helper function to undo
  		 * do_ide_setup_pci_device() on the first device!
  		 */
  		if (ret < 0)
  			goto out;
51d87ed0a   Bartlomiej Zolnierkiewicz   ide: move ide_pci...
578

8c2eece50   Bartlomiej Zolnierkiewicz   ide: call ide_pci...
579
  		/* fixup IRQ */
f65dedfd7   Bartlomiej Zolnierkiewicz   ide: use ide_pci_...
580
  		if (ide_pci_is_in_compatibility_mode(pdev[i])) {
5bae8bf45   Bartlomiej Zolnierkiewicz   ide: use pci_get_...
581
582
  			hw[i*2].irq = pci_get_legacy_ide_irq(pdev[i], 0);
  			hw[i*2 + 1].irq = pci_get_legacy_ide_irq(pdev[i], 1);
f65dedfd7   Bartlomiej Zolnierkiewicz   ide: use ide_pci_...
583
584
  		} else
  			hw[i*2 + 1].irq = hw[i*2].irq = ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
  	}
6cdf6eb35   Bartlomiej Zolnierkiewicz   ide: add ->dev an...
586
587
588
  	ret = ide_host_register(host, d, hws);
  	if (ret)
  		ide_host_free(host);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
590
591
  out:
  	return ret;
  }
6cdf6eb35   Bartlomiej Zolnierkiewicz   ide: add ->dev an...
592
  EXPORT_SYMBOL_GPL(ide_pci_init_two);
ef0b04276   Bartlomiej Zolnierkiewicz   ide: add ide_pci_...
593

ad7c52d09   Bartlomiej Zolnierkiewicz   ide: re-implement...
594
595
596
597
598
599
  int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d,
  		     void *priv)
  {
  	return ide_pci_init_two(dev, NULL, d, priv);
  }
  EXPORT_SYMBOL_GPL(ide_pci_init_one);
ef0b04276   Bartlomiej Zolnierkiewicz   ide: add ide_pci_...
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
  void ide_pci_remove(struct pci_dev *dev)
  {
  	struct ide_host *host = pci_get_drvdata(dev);
  	struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
  	int bars;
  
  	if (host->host_flags & IDE_HFLAG_SINGLE)
  		bars = (1 << 2) - 1;
  	else
  		bars = (1 << 4) - 1;
  
  	if ((host->host_flags & IDE_HFLAG_NO_DMA) == 0) {
  		if (host->host_flags & IDE_HFLAG_CS5520)
  			bars |= (1 << 2);
  		else
  			bars |= (1 << 4);
  	}
  
  	ide_host_remove(host);
  
  	if (dev2)
  		pci_release_selected_regions(dev2, bars);
  	pci_release_selected_regions(dev, bars);
  
  	if (dev2)
  		pci_disable_device(dev2);
  	pci_disable_device(dev);
  }
  EXPORT_SYMBOL_GPL(ide_pci_remove);
feb22b7f8   Bartlomiej Zolnierkiewicz   ide: add proper P...
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
  
  #ifdef CONFIG_PM
  int ide_pci_suspend(struct pci_dev *dev, pm_message_t state)
  {
  	pci_save_state(dev);
  	pci_disable_device(dev);
  	pci_set_power_state(dev, pci_choose_state(dev, state));
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(ide_pci_suspend);
  
  int ide_pci_resume(struct pci_dev *dev)
  {
  	struct ide_host *host = pci_get_drvdata(dev);
  	int rc;
  
  	pci_set_power_state(dev, PCI_D0);
  
  	rc = pci_enable_device(dev);
  	if (rc)
  		return rc;
  
  	pci_restore_state(dev);
  	pci_set_master(dev);
  
  	if (host->init_chipset)
  		host->init_chipset(dev);
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(ide_pci_resume);
  #endif