Blame view

drivers/ide/siimage.c 21 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
   * Copyright (C) 2001-2002	Andre Hedrick <andre@linux-ide.org>
ccd32e221   Alan Cox   ide: Switch to a ...
3
   * Copyright (C) 2003		Red Hat
7b255436d   Sergei Shtylyov   siimage: coding s...
4
   * Copyright (C) 2007-2008	MontaVista Software, Inc.
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
5
   * Copyright (C) 2007-2008	Bartlomiej Zolnierkiewicz
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
   *
   *  May be copied or modified under the terms of the GNU General Public License
   *
bf4c796df   Jeff Garzik   [PATCH] siimage: ...
9
10
11
12
13
14
15
   *  Documentation for CMD680:
   *  http://gkernel.sourceforge.net/specs/sii/sii-0680a-v1.31.pdf.bz2
   *
   *  Documentation for SiI 3112:
   *  http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2
   *
   *  Errata and other documentation only available under NDA.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
19
   *
   *
   *  FAQ Items:
   *	If you are using Marvell SATA-IDE adapters with Maxtor drives
7b255436d   Sergei Shtylyov   siimage: coding s...
20
   *	ensure the system is set up for ATA100/UDMA5, not UDMA6.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
   *
   *	If you are using WD drives with SATA bridges you must set the
7b255436d   Sergei Shtylyov   siimage: coding s...
23
   *	drive to "Single". "Master" will hang.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
   *
   *	If you have strange problems with nVidia chipset systems please
   *	see the SI support documentation and update your system BIOS
3a4fa0a25   Robert P. J. Day   Fix misspellings ...
27
   *	if necessary
8693d3e47   Alan Cox   siimage: DRAC4 note
28
29
30
31
32
   *
   *  The Dell DRAC4 has some interesting features including effectively hot
   *  unplugging/replugging the virtual CD interface when the DRAC is reset.
   *  This often causes drivers/ide/siimage to panic but is ok with the rather
   *  smarter code in libata.
328dcbb63   Bartlomiej Zolnierkiewicz   siimage: PIO mode...
33
34
   *
   * TODO:
328dcbb63   Bartlomiej Zolnierkiewicz   siimage: PIO mode...
35
   * - VDMA support
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
  #include <linux/types.h>
  #include <linux/module.h>
  #include <linux/pci.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
  #include <linux/ide.h>
  #include <linux/init.h>
7b255436d   Sergei Shtylyov   siimage: coding s...
42
  #include <linux/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43

ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
44
  #define DRV_NAME "siimage"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
  /**
   *	pdev_is_sata		-	check if device is SATA
   *	@pdev:	PCI device to check
7b255436d   Sergei Shtylyov   siimage: coding s...
48
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
   *	Returns true if this is a SATA controller
   */
7b255436d   Sergei Shtylyov   siimage: coding s...
51

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
  static int pdev_is_sata(struct pci_dev *pdev)
  {
438c47026   Bartlomiej Zolnierkiewicz   siimage: separate...
54
  #ifdef CONFIG_BLK_DEV_IDE_SATA
7b255436d   Sergei Shtylyov   siimage: coding s...
55
56
57
58
59
60
  	switch (pdev->device) {
  	case PCI_DEVICE_ID_SII_3112:
  	case PCI_DEVICE_ID_SII_1210SA:
  		return 1;
  	case PCI_DEVICE_ID_SII_680:
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
  	}
  	BUG();
438c47026   Bartlomiej Zolnierkiewicz   siimage: separate...
63
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
  	return 0;
  }
438c47026   Bartlomiej Zolnierkiewicz   siimage: separate...
66

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
69
  /**
   *	is_sata			-	check if hwif is SATA
   *	@hwif:	interface to check
7b255436d   Sergei Shtylyov   siimage: coding s...
70
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
   *	Returns true if this is a SATA controller
   */
7b255436d   Sergei Shtylyov   siimage: coding s...
73

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
  static inline int is_sata(ide_hwif_t *hwif)
  {
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
76
  	return pdev_is_sata(to_pci_dev(hwif->dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
80
81
82
83
84
85
  }
  
  /**
   *	siimage_selreg		-	return register base
   *	@hwif: interface
   *	@r: config offset
   *
   *	Turn a config register offset into the right address in either
   *	PCI space or MMIO space to access the control register in question
7b255436d   Sergei Shtylyov   siimage: coding s...
86
87
   *	Thankfully this is a configuration operation, so isn't performance
   *	critical.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
   */
7b255436d   Sergei Shtylyov   siimage: coding s...
89

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
  static unsigned long siimage_selreg(ide_hwif_t *hwif, int r)
  {
  	unsigned long base = (unsigned long)hwif->hwif_data;
7b255436d   Sergei Shtylyov   siimage: coding s...
93

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
  	base += 0xA0 + r;
135721446   Bartlomiej Zolnierkiewicz   ide: remove ->mmi...
95
  	if (hwif->host_flags & IDE_HFLAG_MMIO)
7b255436d   Sergei Shtylyov   siimage: coding s...
96
  		base += hwif->channel << 6;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  	else
7b255436d   Sergei Shtylyov   siimage: coding s...
98
  		base += hwif->channel << 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
100
  	return base;
  }
7b255436d   Sergei Shtylyov   siimage: coding s...
101

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
104
105
106
107
108
109
110
  /**
   *	siimage_seldev		-	return register base
   *	@hwif: interface
   *	@r: config offset
   *
   *	Turn a config register offset into the right address in either
   *	PCI space or MMIO space to access the control register in question
   *	including accounting for the unit shift.
   */
7b255436d   Sergei Shtylyov   siimage: coding s...
111

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
113
  static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
  {
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
114
  	ide_hwif_t *hwif	= drive->hwif;
7b255436d   Sergei Shtylyov   siimage: coding s...
115
  	unsigned long base	= (unsigned long)hwif->hwif_data;
123995b97   Bartlomiej Zolnierkiewicz   ide: use 'drive->...
116
  	u8 unit			= drive->dn & 1;
7b255436d   Sergei Shtylyov   siimage: coding s...
117

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
  	base += 0xA0 + r;
135721446   Bartlomiej Zolnierkiewicz   ide: remove ->mmi...
119
  	if (hwif->host_flags & IDE_HFLAG_MMIO)
7b255436d   Sergei Shtylyov   siimage: coding s...
120
  		base += hwif->channel << 6;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
  	else
7b255436d   Sergei Shtylyov   siimage: coding s...
122
  		base += hwif->channel << 4;
123995b97   Bartlomiej Zolnierkiewicz   ide: use 'drive->...
123
  	base |= unit << unit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
  	return base;
  }
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
126
127
  static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr)
  {
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
128
  	struct ide_host *host = pci_get_drvdata(dev);
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
129
  	u8 tmp = 0;
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
130
  	if (host->host_priv)
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
131
132
133
134
135
136
137
138
139
  		tmp = readb((void __iomem *)addr);
  	else
  		pci_read_config_byte(dev, addr, &tmp);
  
  	return tmp;
  }
  
  static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr)
  {
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
140
  	struct ide_host *host = pci_get_drvdata(dev);
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
141
  	u16 tmp = 0;
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
142
  	if (host->host_priv)
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
143
144
145
146
147
148
149
150
151
  		tmp = readw((void __iomem *)addr);
  	else
  		pci_read_config_word(dev, addr, &tmp);
  
  	return tmp;
  }
  
  static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr)
  {
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
152
153
154
  	struct ide_host *host = pci_get_drvdata(dev);
  
  	if (host->host_priv)
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
155
156
157
158
159
160
161
  		writeb(val, (void __iomem *)addr);
  	else
  		pci_write_config_byte(dev, addr, val);
  }
  
  static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr)
  {
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
162
163
164
  	struct ide_host *host = pci_get_drvdata(dev);
  
  	if (host->host_priv)
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
165
166
167
168
169
170
171
  		writew(val, (void __iomem *)addr);
  	else
  		pci_write_config_word(dev, addr, val);
  }
  
  static void sil_iowrite32(struct pci_dev *dev, u32 val, unsigned long addr)
  {
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
172
173
174
  	struct ide_host *host = pci_get_drvdata(dev);
  
  	if (host->host_priv)
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
175
176
177
178
  		writel(val, (void __iomem *)addr);
  	else
  		pci_write_config_dword(dev, addr, val);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  /**
2d5eaa6dd   Bartlomiej Zolnierkiewicz   ide: rework the c...
180
181
182
183
   *	sil_udma_filter		-	compute UDMA mask
   *	@drive: IDE device
   *
   *	Compute the available UDMA speeds for the device on the interface.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
   *	For the CMD680 this depends on the clocking mode (scsc), for the
2d5eaa6dd   Bartlomiej Zolnierkiewicz   ide: rework the c...
186
   *	SI3112 SATA controller life is a bit simpler.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
   */
2d5eaa6dd   Bartlomiej Zolnierkiewicz   ide: rework the c...
188

438c47026   Bartlomiej Zolnierkiewicz   siimage: separate...
189
  static u8 sil_pata_udma_filter(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  {
7b255436d   Sergei Shtylyov   siimage: coding s...
191
192
193
194
  	ide_hwif_t *hwif	= drive->hwif;
  	struct pci_dev *dev	= to_pci_dev(hwif->dev);
  	unsigned long base	= (unsigned long)hwif->hwif_data;
  	u8 scsc, mask		= 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195

135721446   Bartlomiej Zolnierkiewicz   ide: remove ->mmi...
196
197
198
  	base += (hwif->host_flags & IDE_HFLAG_MMIO) ? 0x4A : 0x8A;
  
  	scsc = sil_ioread8(dev, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199

7b255436d   Sergei Shtylyov   siimage: coding s...
200
201
  	switch (scsc & 0x30) {
  	case 0x10:	/* 133 */
438c47026   Bartlomiej Zolnierkiewicz   siimage: separate...
202
  		mask = ATA_UDMA6;
7b255436d   Sergei Shtylyov   siimage: coding s...
203
204
  		break;
  	case 0x20:	/* 2xPCI */
438c47026   Bartlomiej Zolnierkiewicz   siimage: separate...
205
  		mask = ATA_UDMA6;
7b255436d   Sergei Shtylyov   siimage: coding s...
206
207
  		break;
  	case 0x00:	/* 100 */
438c47026   Bartlomiej Zolnierkiewicz   siimage: separate...
208
  		mask = ATA_UDMA5;
7b255436d   Sergei Shtylyov   siimage: coding s...
209
210
  		break;
  	default: 	/* Disabled ? */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
  		BUG();
7b255436d   Sergei Shtylyov   siimage: coding s...
212
  	}
438c47026   Bartlomiej Zolnierkiewicz   siimage: separate...
213

2d5eaa6dd   Bartlomiej Zolnierkiewicz   ide: rework the c...
214
  	return mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
  }
438c47026   Bartlomiej Zolnierkiewicz   siimage: separate...
216
217
  static u8 sil_sata_udma_filter(ide_drive_t *drive)
  {
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
218
219
220
  	char *m = (char *)&drive->id[ATA_ID_PROD];
  
  	return strstr(m, "Maxtor") ? ATA_UDMA5 : ATA_UDMA6;
438c47026   Bartlomiej Zolnierkiewicz   siimage: separate...
221
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
  /**
88b2b32ba   Bartlomiej Zolnierkiewicz   ide: move ide_con...
223
   *	sil_set_pio_mode	-	set host controller for PIO mode
e085b3cae   Bartlomiej Zolnierkiewicz   ide: change ->set...
224
   *	@hwif: port
88b2b32ba   Bartlomiej Zolnierkiewicz   ide: move ide_con...
225
   *	@drive: drive
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
227
   *
   *	Load the timing settings for this device mode into the
c9ef59ff0   Bartlomiej Zolnierkiewicz   ide: IORDY handli...
228
   *	controller.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
   */
328dcbb63   Bartlomiej Zolnierkiewicz   siimage: PIO mode...
230

e085b3cae   Bartlomiej Zolnierkiewicz   ide: change ->set...
231
  static void sil_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
  {
7b255436d   Sergei Shtylyov   siimage: coding s...
233
234
  	static const u16 tf_speed[]   = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 };
  	static const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
328dcbb63   Bartlomiej Zolnierkiewicz   siimage: PIO mode...
235

165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
236
  	struct pci_dev *dev	= to_pci_dev(hwif->dev);
7e59ea21a   Bartlomiej Zolnierkiewicz   ide: check drive-...
237
  	ide_drive_t *pair	= ide_get_pair_dev(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
240
  	u32 speedt		= 0;
  	u16 speedp		= 0;
  	unsigned long addr	= siimage_seldev(drive, 0x04);
7b255436d   Sergei Shtylyov   siimage: coding s...
241
  	unsigned long tfaddr	= siimage_selreg(hwif,	0x02);
ffe5415c3   Bartlomiej Zolnierkiewicz   siimage: fix ->se...
242
  	unsigned long base	= (unsigned long)hwif->hwif_data;
e085b3cae   Bartlomiej Zolnierkiewicz   ide: change ->set...
243
  	const u8 pio		= drive->pio_mode - XFER_PIO_0;
328dcbb63   Bartlomiej Zolnierkiewicz   siimage: PIO mode...
244
  	u8 tf_pio		= pio;
135721446   Bartlomiej Zolnierkiewicz   ide: remove ->mmi...
245
246
247
  	u8 mmio			= (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
  	u8 addr_mask		= hwif->channel ? (mmio ? 0xF4 : 0x84)
  						: (mmio ? 0xB4 : 0x80);
ffe5415c3   Bartlomiej Zolnierkiewicz   siimage: fix ->se...
248
  	u8 mode			= 0;
123995b97   Bartlomiej Zolnierkiewicz   ide: use 'drive->...
249
  	u8 unit			= drive->dn & 1;
328dcbb63   Bartlomiej Zolnierkiewicz   siimage: PIO mode...
250
251
  
  	/* trim *taskfile* PIO to the slowest of the master/slave */
7e59ea21a   Bartlomiej Zolnierkiewicz   ide: check drive-...
252
  	if (pair) {
bb4306119   Bartlomiej Zolnierkiewicz   siimage: use ->pi...
253
  		u8 pair_pio = pair->pio_mode - XFER_PIO_0;
328dcbb63   Bartlomiej Zolnierkiewicz   siimage: PIO mode...
254
255
256
  
  		if (pair_pio < tf_pio)
  			tf_pio = pair_pio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
  	}
075cb6551   Sergei Shtylyov   siimage: PIO1/2 t...
258

328dcbb63   Bartlomiej Zolnierkiewicz   siimage: PIO mode...
259
260
261
  	/* cheat for now and use the docs */
  	speedp = data_speed[pio];
  	speedt = tf_speed[tf_pio];
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
262
263
264
265
266
267
  	sil_iowrite16(dev, speedp, addr);
  	sil_iowrite16(dev, speedt, tfaddr);
  
  	/* now set up IORDY */
  	speedp = sil_ioread16(dev, tfaddr - 2);
  	speedp &= ~0x200;
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
268
269
270
  
  	mode = sil_ioread8(dev, base + addr_mask);
  	mode &= ~(unit ? 0x30 : 0x03);
c9ef59ff0   Bartlomiej Zolnierkiewicz   ide: IORDY handli...
271
272
273
274
275
276
277
  
  	if (ide_pio_need_iordy(drive, pio)) {
  		speedp |= 0x200;
  		mode |= unit ? 0x10 : 0x01;
  	}
  
  	sil_iowrite16(dev, speedp, tfaddr - 2);
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
278
  	sil_iowrite8(dev, mode, base + addr_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
  /**
88b2b32ba   Bartlomiej Zolnierkiewicz   ide: move ide_con...
281
   *	sil_set_dma_mode	-	set host controller for DMA mode
8776168ca   Bartlomiej Zolnierkiewicz   ide: change ->set...
282
   *	@hwif: port
88b2b32ba   Bartlomiej Zolnierkiewicz   ide: move ide_con...
283
   *	@drive: drive
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
   *
88b2b32ba   Bartlomiej Zolnierkiewicz   ide: move ide_con...
285
   *	Tune the SiI chipset for the desired DMA mode.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
   */
f212ff28f   Bartlomiej Zolnierkiewicz   ide: move ide_rat...
287

8776168ca   Bartlomiej Zolnierkiewicz   ide: change ->set...
288
  static void sil_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
  {
7b255436d   Sergei Shtylyov   siimage: coding s...
290
291
292
  	static const u8 ultra6[] = { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 };
  	static const u8 ultra5[] = { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 };
  	static const u16 dma[]	 = { 0x2208, 0x10C2, 0x10C1 };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293

36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
294
  	struct pci_dev *dev	= to_pci_dev(hwif->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
  	unsigned long base	= (unsigned long)hwif->hwif_data;
123995b97   Bartlomiej Zolnierkiewicz   ide: use 'drive->...
296
297
  	u16 ultra = 0, multi	= 0;
  	u8 mode = 0, unit	= drive->dn & 1;
135721446   Bartlomiej Zolnierkiewicz   ide: remove ->mmi...
298
299
300
  	u8 mmio			= (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
  	u8 scsc = 0, addr_mask	= hwif->channel ? (mmio ? 0xF4 : 0x84)
  						: (mmio ? 0xB4 : 0x80);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
302
  	unsigned long ma	= siimage_seldev(drive, 0x08);
  	unsigned long ua	= siimage_seldev(drive, 0x0C);
8776168ca   Bartlomiej Zolnierkiewicz   ide: change ->set...
303
  	const u8 speed		= drive->dma_mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304

135721446   Bartlomiej Zolnierkiewicz   ide: remove ->mmi...
305
  	scsc  = sil_ioread8 (dev, base + (mmio ? 0x4A : 0x8A));
7b255436d   Sergei Shtylyov   siimage: coding s...
306
  	mode  = sil_ioread8 (dev, base + addr_mask);
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
307
308
  	multi = sil_ioread16(dev, ma);
  	ultra = sil_ioread16(dev, ua);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309

7b255436d   Sergei Shtylyov   siimage: coding s...
310
  	mode  &= ~(unit ? 0x30 : 0x03);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
312
313
314
  	ultra &= ~0x3F;
  	scsc = ((scsc & 0x30) == 0x00) ? 0 : 1;
  
  	scsc = is_sata(hwif) ? 1 : scsc;
4db90a145   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
315
  	if (speed >= XFER_UDMA_0) {
7b255436d   Sergei Shtylyov   siimage: coding s...
316
317
318
319
  		multi  = dma[2];
  		ultra |= scsc ? ultra6[speed - XFER_UDMA_0] :
  				ultra5[speed - XFER_UDMA_0];
  		mode  |= unit ? 0x30 : 0x03;
4db90a145   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
320
321
  	} else {
  		multi = dma[speed - XFER_MW_DMA_0];
7b255436d   Sergei Shtylyov   siimage: coding s...
322
  		mode |= unit ? 0x20 : 0x02;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
  	}
7b255436d   Sergei Shtylyov   siimage: coding s...
324
  	sil_iowrite8 (dev, mode, base + addr_mask);
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
325
326
  	sil_iowrite16(dev, multi, ma);
  	sil_iowrite16(dev, ultra, ua);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
  }
ec053e4ee   Sergei Shtylyov   siimage: implemen...
328
329
330
331
332
333
334
335
336
  static int sil_test_irq(ide_hwif_t *hwif)
  {
  	struct pci_dev *dev	= to_pci_dev(hwif->dev);
  	unsigned long addr	= siimage_selreg(hwif, 1);
  	u8 val			= sil_ioread8(dev, addr);
  
  	/* Return 1 if INTRQ asserted */
  	return (val & 8) ? 1 : 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
  /**
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
338
   *	siimage_mmio_dma_test_irq	-	check we caused an IRQ
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
341
342
343
   *	@drive: drive we are testing
   *
   *	Check if we caused an IDE DMA interrupt. We may also have caused
   *	SATA status interrupts, if so we clean them up and continue.
   */
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
344
345
  
  static int siimage_mmio_dma_test_irq(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  {
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
347
  	ide_hwif_t *hwif	= drive->hwif;
835457def   Bartlomiej Zolnierkiewicz   ide: remove SATA_...
348
349
  	void __iomem *sata_error_addr
  		= (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350

835457def   Bartlomiej Zolnierkiewicz   ide: remove SATA_...
351
  	if (sata_error_addr) {
7b255436d   Sergei Shtylyov   siimage: coding s...
352
353
354
  		unsigned long base	= (unsigned long)hwif->hwif_data;
  		u32 ext_stat		= readl((void __iomem *)(base + 0x10));
  		u8 watchdog		= 0;
835457def   Bartlomiej Zolnierkiewicz   ide: remove SATA_...
355

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
  		if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) {
835457def   Bartlomiej Zolnierkiewicz   ide: remove SATA_...
357
358
359
  			u32 sata_error = readl(sata_error_addr);
  
  			writel(sata_error, sata_error_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
  			watchdog = (sata_error & 0x00680000) ? 1 : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
362
363
  			printk(KERN_WARNING "%s: sata_error = 0x%08x, "
  				"watchdog = %d, %s
  ",
7b255436d   Sergei Shtylyov   siimage: coding s...
364
365
  				drive->name, sata_error, watchdog, __func__);
  		} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
  			watchdog = (ext_stat & 0x8000) ? 1 : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367

7b255436d   Sergei Shtylyov   siimage: coding s...
368
  		ext_stat >>= 16;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
370
371
372
373
  		if (!(ext_stat & 0x0404) && !watchdog)
  			return 0;
  	}
  
  	/* return 1 if INTR asserted */
cab7f8eda   Bartlomiej Zolnierkiewicz   ide: remove ->dma...
374
  	if (readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)) & 4)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
  		return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
377
  	return 0;
  }
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
378
379
  static int siimage_dma_test_irq(ide_drive_t *drive)
  {
135721446   Bartlomiej Zolnierkiewicz   ide: remove ->mmi...
380
  	if (drive->hwif->host_flags & IDE_HFLAG_MMIO)
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
381
382
  		return siimage_mmio_dma_test_irq(drive);
  	else
74414a912   Sergei Shtylyov   siimage: use ide_...
383
  		return ide_dma_test_irq(drive);
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
384
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
  /**
438c47026   Bartlomiej Zolnierkiewicz   siimage: separate...
386
   *	sil_sata_reset_poll	-	wait for SATA reset
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
388
389
390
391
   *	@drive: drive we are resetting
   *
   *	Poll the SATA phy and see whether it has come back from the dead
   *	yet.
   */
438c47026   Bartlomiej Zolnierkiewicz   siimage: separate...
392
393
  
  static int sil_sata_reset_poll(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
  {
835457def   Bartlomiej Zolnierkiewicz   ide: remove SATA_...
395
396
397
398
399
400
401
  	ide_hwif_t *hwif = drive->hwif;
  	void __iomem *sata_status_addr
  		= (void __iomem *)hwif->sata_scr[SATA_STATUS_OFFSET];
  
  	if (sata_status_addr) {
  		/* SATA Status is available only when in MMIO mode */
  		u32 sata_stat = readl(sata_status_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402

835457def   Bartlomiej Zolnierkiewicz   ide: remove SATA_...
403
  		if ((sata_stat & 0x03) != 0x03) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
405
  			printk(KERN_WARNING "%s: reset phy dead, status=0x%08x
  ",
835457def   Bartlomiej Zolnierkiewicz   ide: remove SATA_...
406
  					    hwif->name, sata_stat);
64a8f00ff   Elias Oltmanns   IDE: Report error...
407
  			return -ENXIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
  	}
438c47026   Bartlomiej Zolnierkiewicz   siimage: separate...
410
411
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
413
414
  }
  
  /**
438c47026   Bartlomiej Zolnierkiewicz   siimage: separate...
415
   *	sil_sata_pre_reset	-	reset hook
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
417
418
419
420
   *	@drive: IDE device being reset
   *
   *	For the SATA devices we need to handle recalibration/geometry
   *	differently
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421

438c47026   Bartlomiej Zolnierkiewicz   siimage: separate...
422
423
424
  static void sil_sata_pre_reset(ide_drive_t *drive)
  {
  	if (drive->media == ide_disk) {
ca1b96e00   Bartlomiej Zolnierkiewicz   ide: replace spec...
425
426
  		drive->special_flags &=
  			~(IDE_SFLAG_SET_GEOMETRY | IDE_SFLAG_RECALIBRATE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
428
429
430
  	}
  }
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
432
   *	init_chipset_siimage	-	set up an SI device
   *	@dev: PCI device
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
   *
   *	Perform the initial PCI set up for this device. Attempt to switch
7b255436d   Sergei Shtylyov   siimage: coding s...
435
   *	to 133 MHz clocking if the system isn't already set up to do it.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
   */
2ed0ef543   Bartlomiej Zolnierkiewicz   ide: fix ->init_c...
437
  static int init_chipset_siimage(struct pci_dev *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
  {
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
439
440
  	struct ide_host *host = pci_get_drvdata(dev);
  	void __iomem *ioaddr = host->host_priv;
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
441
  	unsigned long base, scsc_addr;
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
442
  	u8 rev = dev->revision, tmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443

fc212bb1f   Bartlomiej Zolnierkiewicz   ide: use pci_dev-...
444
  	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, rev ? 1 : 255);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445

4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
446
447
  	if (ioaddr)
  		pci_set_master(dev);
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
448
449
450
451
452
453
454
455
456
457
458
459
460
  
  	base = (unsigned long)ioaddr;
  
  	if (ioaddr && pdev_is_sata(dev)) {
  		u32 tmp32, irq_mask;
  
  		/* make sure IDE0/1 interrupts are not masked */
  		irq_mask = (1 << 22) | (1 << 23);
  		tmp32 = readl(ioaddr + 0x48);
  		if (tmp32 & irq_mask) {
  			tmp32 &= ~irq_mask;
  			writel(tmp32, ioaddr + 0x48);
  			readl(ioaddr + 0x48); /* flush */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
  		}
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
462
463
  		writel(0, ioaddr + 0x148);
  		writel(0, ioaddr + 0x1C8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
  	}
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
465
466
467
468
469
470
471
472
  	sil_iowrite8(dev, 0, base ? (base + 0xB4) : 0x80);
  	sil_iowrite8(dev, 0, base ? (base + 0xF4) : 0x84);
  
  	scsc_addr = base ? (base + 0x4A) : 0x8A;
  	tmp = sil_ioread8(dev, scsc_addr);
  
  	switch (tmp & 0x30) {
  	case 0x00:
7b255436d   Sergei Shtylyov   siimage: coding s...
473
  		/* On 100 MHz clocking, try and switch to 133 MHz */
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
474
475
476
477
478
479
480
481
482
483
484
  		sil_iowrite8(dev, tmp | 0x10, scsc_addr);
  		break;
  	case 0x30:
  		/* Clocking is disabled, attempt to force 133MHz clocking. */
  		sil_iowrite8(dev, tmp & ~0x20, scsc_addr);
  	case 0x10:
  		/* On 133Mhz clocking. */
  		break;
  	case 0x20:
  		/* On PCIx2 clocking. */
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
  	}
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
486
  	tmp = sil_ioread8(dev, scsc_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487

7b255436d   Sergei Shtylyov   siimage: coding s...
488
  	sil_iowrite8 (dev,       0x72, base + 0xA1);
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
489
490
491
492
  	sil_iowrite16(dev,     0x328A, base + 0xA2);
  	sil_iowrite32(dev, 0x62DD62DD, base + 0xA4);
  	sil_iowrite32(dev, 0x43924392, base + 0xA8);
  	sil_iowrite32(dev, 0x40094009, base + 0xAC);
7b255436d   Sergei Shtylyov   siimage: coding s...
493
  	sil_iowrite8 (dev,       0x72, base ? (base + 0xE1) : 0xB1);
165701d9f   Bartlomiej Zolnierkiewicz   siimage: add sil_...
494
495
496
497
498
499
500
501
502
503
504
  	sil_iowrite16(dev,     0x328A, base ? (base + 0xE2) : 0xB2);
  	sil_iowrite32(dev, 0x62DD62DD, base ? (base + 0xE4) : 0xB4);
  	sil_iowrite32(dev, 0x43924392, base ? (base + 0xE8) : 0xB8);
  	sil_iowrite32(dev, 0x40094009, base ? (base + 0xEC) : 0xBC);
  
  	if (base && pdev_is_sata(dev)) {
  		writel(0xFFFF0000, ioaddr + 0x108);
  		writel(0xFFFF0000, ioaddr + 0x188);
  		writel(0x00680000, ioaddr + 0x148);
  		writel(0x00680000, ioaddr + 0x1C8);
  	}
24cc434ac   Bartlomiej Zolnierkiewicz   siimage: remove p...
505
506
507
508
509
510
  	/* report the clocking mode of the controller */
  	if (!pdev_is_sata(dev)) {
  		static const char *clk_str[] =
  			{ "== 100", "== 133", "== 2X PCI", "DISABLED!" };
  
  		tmp >>= 4;
a326b02b0   Bartlomiej Zolnierkiewicz   ide: drop 'name' ...
511
512
513
  		printk(KERN_INFO DRV_NAME " %s: BASE CLOCK %s
  ",
  			pci_name(dev), clk_str[tmp & 3]);
24cc434ac   Bartlomiej Zolnierkiewicz   siimage: remove p...
514
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
518
519
520
521
522
523
524
  	return 0;
  }
  
  /**
   *	init_mmio_iops_siimage	-	set up the iops for MMIO
   *	@hwif: interface to set up
   *
   *	The basic setup here is fairly simple, we can use standard MMIO
   *	operations. However we do have to set the taskfile register offsets
7b255436d   Sergei Shtylyov   siimage: coding s...
525
   *	by hand as there isn't a standard defined layout for them this time.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
527
   *
   *	The hardware supports buffered taskfiles and also some rather nice
19c1ef5f6   Alan Cox   [PATCH] ide: clea...
528
   *	extended PRD tables. For better SI3112 support use the libata driver
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
530
531
532
   */
  
  static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
  {
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
533
  	struct pci_dev *dev	= to_pci_dev(hwif->dev);
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
534
535
  	struct ide_host *host	= pci_get_drvdata(dev);
  	void *addr		= host->host_priv;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
  	u8 ch			= hwif->channel;
4c3032d8a   Bartlomiej Zolnierkiewicz   ide: add struct i...
537
  	struct ide_io_ports *io_ports = &hwif->io_ports;
7b255436d   Sergei Shtylyov   siimage: coding s...
538
  	unsigned long base;
4c3032d8a   Bartlomiej Zolnierkiewicz   ide: add struct i...
539

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
  	/*
7b255436d   Sergei Shtylyov   siimage: coding s...
541
  	 *	Fill in the basic hwif bits
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542
  	 */
c5dd43ec6   Bartlomiej Zolnierkiewicz   ide: add IDE_HFLA...
543
  	hwif->host_flags |= IDE_HFLAG_MMIO;
761052e67   Bartlomiej Zolnierkiewicz   ide: remove ->INB...
544

7b255436d   Sergei Shtylyov   siimage: coding s...
545
  	hwif->hwif_data	= addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
547
  
  	/*
7b255436d   Sergei Shtylyov   siimage: coding s...
548
549
  	 *	Now set up the hw. We have to do this ourselves as the
  	 *	MMIO layout isn't the same as the standard port based I/O.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
  	 */
4c3032d8a   Bartlomiej Zolnierkiewicz   ide: add struct i...
551
  	memset(io_ports, 0, sizeof(*io_ports));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
553
554
555
556
557
558
559
  
  	base = (unsigned long)addr;
  	if (ch)
  		base += 0xC0;
  	else
  		base += 0x80;
  
  	/*
7b255436d   Sergei Shtylyov   siimage: coding s...
560
561
562
  	 *	The buffered task file doesn't have status/control, so we
  	 *	can't currently use it sanely since we want to use LBA48 mode.
  	 */
4c3032d8a   Bartlomiej Zolnierkiewicz   ide: add struct i...
563
564
565
566
567
568
569
570
571
  	io_ports->data_addr	= base;
  	io_ports->error_addr	= base + 1;
  	io_ports->nsect_addr	= base + 2;
  	io_ports->lbal_addr	= base + 3;
  	io_ports->lbam_addr	= base + 4;
  	io_ports->lbah_addr	= base + 5;
  	io_ports->device_addr	= base + 6;
  	io_ports->status_addr	= base + 7;
  	io_ports->ctl_addr	= base + 10;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572
573
574
575
576
577
578
579
  
  	if (pdev_is_sata(dev)) {
  		base = (unsigned long)addr;
  		if (ch)
  			base += 0x80;
  		hwif->sata_scr[SATA_STATUS_OFFSET]	= base + 0x104;
  		hwif->sata_scr[SATA_ERROR_OFFSET]	= base + 0x108;
  		hwif->sata_scr[SATA_CONTROL_OFFSET]	= base + 0x100;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  	}
9239b3339   Bartlomiej Zolnierkiewicz   ide: remove write...
581
  	hwif->irq = dev->irq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582

9239b3339   Bartlomiej Zolnierkiewicz   ide: remove write...
583
  	hwif->dma_base = (unsigned long)addr + (ch ? 0x08 : 0x00);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
585
586
587
  }
  
  static int is_dev_seagate_sata(ide_drive_t *drive)
  {
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
588
589
  	const char *s	= (const char *)&drive->id[ATA_ID_PROD];
  	unsigned len	= strnlen(s, ATA_ID_PROD_LEN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590

7b255436d   Sergei Shtylyov   siimage: coding s...
591
  	if ((len > 4) && (!memcmp(s, "ST", 2)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
593
594
595
596
597
598
  		if ((!memcmp(s + len - 2, "AS", 2)) ||
  		    (!memcmp(s + len - 3, "ASL", 3))) {
  			printk(KERN_INFO "%s: applying pessimistic Seagate "
  					 "errata fix
  ", drive->name);
  			return 1;
  		}
7b255436d   Sergei Shtylyov   siimage: coding s...
599

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
601
602
603
  	return 0;
  }
  
  /**
f01393e48   Bartlomiej Zolnierkiewicz   ide: merge ->fixu...
604
605
   *	sil_quirkproc		-	post probe fixups
   *	@drive: drive
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606
607
608
609
610
   *
   *	Called after drive probe we use this to decide whether the
   *	Seagate fixup must be applied. This used to be in init_iops but
   *	that can occur before we know what drives are present.
   */
36de99480   Bartlomiej Zolnierkiewicz   ide: ->quirkproc ...
611
  static void sil_quirkproc(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
  {
f01393e48   Bartlomiej Zolnierkiewicz   ide: merge ->fixu...
613
  	ide_hwif_t *hwif = drive->hwif;
7b255436d   Sergei Shtylyov   siimage: coding s...
614
  	/* Try and rise the rqsize */
f01393e48   Bartlomiej Zolnierkiewicz   ide: merge ->fixu...
615
  	if (!is_sata(hwif) || !is_dev_seagate_sata(drive))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
  		hwif->rqsize = 128;
  }
  
  /**
   *	init_iops_siimage	-	set up iops
   *	@hwif: interface to set up
   *
   *	Do the basic setup for the SIIMAGE hardware interface
   *	and then do the MMIO setup if we can. This is the first
   *	look in we get for setting up the hwif so that we
   *	can get the iops right before using them.
   */
  
  static void __devinit init_iops_siimage(ide_hwif_t *hwif)
  {
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
631
  	struct pci_dev *dev = to_pci_dev(hwif->dev);
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
632
  	struct ide_host *host = pci_get_drvdata(dev);
36501650e   Bartlomiej Zolnierkiewicz   ide: keep pointer...
633

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
635
636
637
  	hwif->hwif_data = NULL;
  
  	/* Pessimal until we finish probing */
  	hwif->rqsize = 15;
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
638
639
  	if (host->host_priv)
  		init_mmio_iops_siimage(hwif);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
640
641
642
  }
  
  /**
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
643
   *	sil_cable_detect	-	cable detection
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
645
   *	@hwif: interface to check
   *
7b255436d   Sergei Shtylyov   siimage: coding s...
646
   *	Check for the presence of an ATA66 capable cable on the interface.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
   */
f454cbe8c   Bartlomiej Zolnierkiewicz   ide: ->cable_dete...
648
  static u8 sil_cable_detect(ide_hwif_t *hwif)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
  {
7b255436d   Sergei Shtylyov   siimage: coding s...
650
651
652
  	struct pci_dev *dev	= to_pci_dev(hwif->dev);
  	unsigned long addr	= siimage_selreg(hwif, 0);
  	u8 ata66		= sil_ioread8(dev, addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653

49521f97c   Bartlomiej Zolnierkiewicz   ide: add short ca...
654
  	return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
  }
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
656
657
658
659
  static const struct ide_port_ops sil_pata_port_ops = {
  	.set_pio_mode		= sil_set_pio_mode,
  	.set_dma_mode		= sil_set_dma_mode,
  	.quirkproc		= sil_quirkproc,
ec053e4ee   Sergei Shtylyov   siimage: implemen...
660
  	.test_irq		= sil_test_irq,
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
661
662
663
664
665
666
667
668
669
670
  	.udma_filter		= sil_pata_udma_filter,
  	.cable_detect		= sil_cable_detect,
  };
  
  static const struct ide_port_ops sil_sata_port_ops = {
  	.set_pio_mode		= sil_set_pio_mode,
  	.set_dma_mode		= sil_set_dma_mode,
  	.reset_poll		= sil_sata_reset_poll,
  	.pre_reset		= sil_sata_pre_reset,
  	.quirkproc		= sil_quirkproc,
ec053e4ee   Sergei Shtylyov   siimage: implemen...
671
  	.test_irq		= sil_test_irq,
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
672
673
674
  	.udma_filter		= sil_sata_udma_filter,
  	.cable_detect		= sil_cable_detect,
  };
b26b0c590   Benjamin Herrenschmidt   ide: fix crash at...
675
676
677
  static const struct ide_dma_ops sil_dma_ops = {
  	.dma_host_set		= ide_dma_host_set,
  	.dma_setup		= ide_dma_setup,
b26b0c590   Benjamin Herrenschmidt   ide: fix crash at...
678
  	.dma_start		= ide_dma_start,
653bcf529   Bartlomiej Zolnierkiewicz   ide: __ide_dma_en...
679
  	.dma_end		= ide_dma_end,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
680
  	.dma_test_irq		= siimage_dma_test_irq,
22117d6ea   Bartlomiej Zolnierkiewicz   ide: add ->dma_ti...
681
  	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
b26b0c590   Benjamin Herrenschmidt   ide: fix crash at...
682
  	.dma_lost_irq		= ide_dma_lost_irq,
592b53152   Sergei Shtylyov   ide: move read_sf...
683
  	.dma_sff_read_status	= ide_dma_sff_read_status,
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
684
  };
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
685
  #define DECLARE_SII_DEV(p_ops)				\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
  	{						\
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
687
  		.name		= DRV_NAME,		\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688
689
  		.init_chipset	= init_chipset_siimage,	\
  		.init_iops	= init_iops_siimage,	\
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
690
  		.port_ops	= p_ops,		\
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
691
  		.dma_ops	= &sil_dma_ops,		\
4099d1432   Bartlomiej Zolnierkiewicz   ide: add PIO masks
692
  		.pio_mask	= ATA_PIO4,		\
5f8b6c348   Bartlomiej Zolnierkiewicz   ide: add ->mwdma_...
693
694
  		.mwdma_mask	= ATA_MWDMA2,		\
  		.udma_mask	= ATA_UDMA6,		\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
695
  	}
856204360   Bartlomiej Zolnierkiewicz   ide: constify str...
696
  static const struct ide_port_info siimage_chipsets[] __devinitdata = {
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
697
698
  	/* 0: SiI680 */  DECLARE_SII_DEV(&sil_pata_port_ops),
  	/* 1: SiI3112 */ DECLARE_SII_DEV(&sil_sata_port_ops)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
700
701
  };
  
  /**
7b255436d   Sergei Shtylyov   siimage: coding s...
702
   *	siimage_init_one	-	PCI layer discovery entry
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
705
   *	@dev: PCI device
   *	@id: ident table entry
   *
7b255436d   Sergei Shtylyov   siimage: coding s...
706
   *	Called by the PCI code when it finds an SiI680 or SiI3112 controller.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707
708
   *	We then use the IDE PCI generic helper to do most of the work.
   */
7b255436d   Sergei Shtylyov   siimage: coding s...
709
710
711
  
  static int __devinit siimage_init_one(struct pci_dev *dev,
  				      const struct pci_device_id *id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
712
  {
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
713
714
715
716
  	void __iomem *ioaddr = NULL;
  	resource_size_t bar5 = pci_resource_start(dev, 5);
  	unsigned long barsize = pci_resource_len(dev, 5);
  	int rc;
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
717
718
  	struct ide_port_info d;
  	u8 idx = id->driver_data;
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
719
  	u8 BA5_EN;
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
720
721
722
723
724
725
726
  
  	d = siimage_chipsets[idx];
  
  	if (idx) {
  		static int first = 1;
  
  		if (first) {
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
727
  			printk(KERN_INFO DRV_NAME ": For full SATA support you "
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
728
729
730
731
732
733
734
  				"should use the libata sata_sil module.
  ");
  			first = 0;
  		}
  
  		d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
  	}
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
735
736
737
738
739
740
741
742
743
744
745
  	rc = pci_enable_device(dev);
  	if (rc)
  		return rc;
  
  	pci_read_config_byte(dev, 0x8A, &BA5_EN);
  	if ((BA5_EN & 0x01) || bar5) {
  		/*
  		* Drop back to PIO if we can't map the MMIO. Some systems
  		* seem to get terminally confused in the PCI spaces.
  		*/
  		if (!request_mem_region(bar5, barsize, d.name)) {
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
746
  			printk(KERN_WARNING DRV_NAME " %s: MMIO ports not "
28cfd8af5   Bartlomiej Zolnierkiewicz   ide: include PCI ...
747
748
  				"available
  ", pci_name(dev));
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
749
  		} else {
1f1ab2745   Arjan van de Ven   ide: two more pci...
750
  			ioaddr = pci_ioremap_bar(dev, 5);
4c674235d   Bartlomiej Zolnierkiewicz   siimage: convert ...
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
  			if (ioaddr == NULL)
  				release_mem_region(bar5, barsize);
  		}
  	}
  
  	rc = ide_pci_init_one(dev, &d, ioaddr);
  	if (rc) {
  		if (ioaddr) {
  			iounmap(ioaddr);
  			release_mem_region(bar5, barsize);
  		}
  		pci_disable_device(dev);
  	}
  
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
766
  }
fe3825808   Bartlomiej Zolnierkiewicz   siimage: add ->re...
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
  static void __devexit siimage_remove(struct pci_dev *dev)
  {
  	struct ide_host *host = pci_get_drvdata(dev);
  	void __iomem *ioaddr = host->host_priv;
  
  	ide_pci_remove(dev);
  
  	if (ioaddr) {
  		resource_size_t bar5 = pci_resource_start(dev, 5);
  		unsigned long barsize = pci_resource_len(dev, 5);
  
  		iounmap(ioaddr);
  		release_mem_region(bar5, barsize);
  	}
  
  	pci_disable_device(dev);
  }
9cbcc5e3c   Bartlomiej Zolnierkiewicz   ide: use PCI_VDEV...
784
785
  static const struct pci_device_id siimage_pci_tbl[] = {
  	{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680),    0 },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
786
  #ifdef CONFIG_BLK_DEV_IDE_SATA
9cbcc5e3c   Bartlomiej Zolnierkiewicz   ide: use PCI_VDEV...
787
  	{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_3112),   1 },
ced3ec8aa   Bartlomiej Zolnierkiewicz   ide: prefix messa...
788
  	{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 1 },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
790
791
792
  #endif
  	{ 0, },
  };
  MODULE_DEVICE_TABLE(pci, siimage_pci_tbl);
a9ab09e26   Bartlomiej Zolnierkiewicz   ide: use unique n...
793
  static struct pci_driver siimage_pci_driver = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794
795
796
  	.name		= "SiI_IDE",
  	.id_table	= siimage_pci_tbl,
  	.probe		= siimage_init_one,
a69999e28   Adrian Bunk   drivers/ide/pci/:...
797
  	.remove		= __devexit_p(siimage_remove),
feb22b7f8   Bartlomiej Zolnierkiewicz   ide: add proper P...
798
799
  	.suspend	= ide_pci_suspend,
  	.resume		= ide_pci_resume,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
  };
82ab1eece   Bartlomiej Zolnierkiewicz   ide: add missing ...
801
  static int __init siimage_ide_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
  {
a9ab09e26   Bartlomiej Zolnierkiewicz   ide: use unique n...
803
  	return ide_pci_register_driver(&siimage_pci_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
804
  }
fe3825808   Bartlomiej Zolnierkiewicz   siimage: add ->re...
805
806
  static void __exit siimage_ide_exit(void)
  {
a9ab09e26   Bartlomiej Zolnierkiewicz   ide: use unique n...
807
  	pci_unregister_driver(&siimage_pci_driver);
fe3825808   Bartlomiej Zolnierkiewicz   siimage: add ->re...
808
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809
  module_init(siimage_ide_init);
fe3825808   Bartlomiej Zolnierkiewicz   siimage: add ->re...
810
  module_exit(siimage_ide_exit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811
812
813
814
  
  MODULE_AUTHOR("Andre Hedrick, Alan Cox");
  MODULE_DESCRIPTION("PCI driver module for SiI IDE");
  MODULE_LICENSE("GPL");