Blame view

drivers/ata/sata_sx4.c 39.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
  /*
   *  sata_sx4.c - Promise SATA
   *
   *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
   *  		    Please ALWAYS copy linux-ide@vger.kernel.org
   *		    on emails.
   *
   *  Copyright 2003-2004 Red Hat, Inc.
   *
af36d7f0d   Jeff Garzik   [libata] license ...
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2, or (at your option)
   *  any later version.
   *
   *  This program is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *  along with this program; see the file COPYING.  If not, write to
   *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
   *
   *
   *  libata documentation is available via 'make {ps|pdf}docs',
   *  as Documentation/DocBook/libata.*
   *
   *  Hardware documentation available under NDA.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
   *
   */
a09060ffe   Jeff Garzik   [libata] sata_sx4...
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
  /*
  	Theory of operation
  	-------------------
  
  	The SX4 (PDC20621) chip features a single Host DMA (HDMA) copy
  	engine, DIMM memory, and four ATA engines (one per SATA port).
  	Data is copied to/from DIMM memory by the HDMA engine, before
  	handing off to one (or more) of the ATA engines.  The ATA
  	engines operate solely on DIMM memory.
  
  	The SX4 behaves like a PATA chip, with no SATA controls or
  	knowledge whatsoever, leading to the presumption that
  	PATA<->SATA bridges exist on SX4 boards, external to the
  	PDC20621 chip itself.
  
  	The chip is quite capable, supporting an XOR engine and linked
  	hardware commands (permits a string to transactions to be
  	submitted and waited-on as a single unit), and an optional
  	microprocessor.
  
  	The limiting factor is largely software.  This Linux driver was
  	written to multiplex the single HDMA engine to copy disk
  	transactions into a fixed DIMM memory space, from where an ATA
  	engine takes over.  As a result, each WRITE looks like this:
  
  		submit HDMA packet to hardware
  		hardware copies data from system memory to DIMM
  		hardware raises interrupt
  
  		submit ATA packet to hardware
  		hardware executes ATA WRITE command, w/ data in DIMM
  		hardware raises interrupt
2dcb407e6   Jeff Garzik   [libata] checkpat...
64

a09060ffe   Jeff Garzik   [libata] sata_sx4...
65
66
67
68
69
  	and each READ looks like this:
  
  		submit ATA packet to hardware
  		hardware executes ATA READ command, w/ data in DIMM
  		hardware raises interrupt
2dcb407e6   Jeff Garzik   [libata] checkpat...
70

a09060ffe   Jeff Garzik   [libata] sata_sx4...
71
72
73
74
75
76
77
78
  		submit HDMA packet to hardware
  		hardware copies data from DIMM to system memory
  		hardware raises interrupt
  
  	This is a very slow, lock-step way of doing things that can
  	certainly be improved by motivated kernel hackers.
  
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/pci.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
82
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
84
85
86
  #include <linux/init.h>
  #include <linux/blkdev.h>
  #include <linux/delay.h>
  #include <linux/interrupt.h>
a9524a76f   Jeff Garzik   [libata] use dev_...
87
  #include <linux/device.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
  #include <scsi/scsi_host.h>
193515d51   Jeff Garzik   [libata] eliminat...
89
  #include <scsi/scsi_cmnd.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
  #include <linux/libata.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
  #include "sata_promise.h"
  
  #define DRV_NAME	"sata_sx4"
2a3103ce4   Jeff Garzik   [libata] Bump dri...
94
  #define DRV_VERSION	"0.12"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
97
  
  
  enum {
0d5ff5667   Tejun Heo   libata: convert t...
98
99
  	PDC_MMIO_BAR		= 3,
  	PDC_DIMM_BAR		= 4,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
103
104
105
  	PDC_PRD_TBL		= 0x44,	/* Direct command DMA table addr */
  
  	PDC_PKT_SUBMIT		= 0x40, /* Command packet pointer addr */
  	PDC_HDMA_PKT_SUBMIT	= 0x100, /* Host DMA packet pointer addr */
  	PDC_INT_SEQMASK		= 0x40,	/* Mask of asserted SEQ INTs */
  	PDC_HDMA_CTLSTAT	= 0x12C, /* Host DMA control / status */
a09060ffe   Jeff Garzik   [libata] sata_sx4...
106
  	PDC_CTLSTAT		= 0x60,	/* IDEn control / status */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  	PDC_20621_SEQCTL	= 0x400,
  	PDC_20621_SEQMASK	= 0x480,
  	PDC_20621_GENERAL_CTL	= 0x484,
  	PDC_20621_PAGE_SIZE	= (32 * 1024),
  
  	/* chosen, not constant, values; we design our own DIMM mem map */
  	PDC_20621_DIMM_WINDOW	= 0x0C,	/* page# for 32K DIMM window */
  	PDC_20621_DIMM_BASE	= 0x00200000,
  	PDC_20621_DIMM_DATA	= (64 * 1024),
  	PDC_DIMM_DATA_STEP	= (256 * 1024),
  	PDC_DIMM_WINDOW_STEP	= (8 * 1024),
  	PDC_DIMM_HOST_PRD	= (6 * 1024),
  	PDC_DIMM_HOST_PKT	= (128 * 0),
  	PDC_DIMM_HPKT_PRD	= (128 * 1),
  	PDC_DIMM_ATA_PKT	= (128 * 2),
  	PDC_DIMM_APKT_PRD	= (128 * 3),
  	PDC_DIMM_HEADER_SZ	= PDC_DIMM_APKT_PRD + 128,
  	PDC_PAGE_WINDOW		= 0x40,
  	PDC_PAGE_DATA		= PDC_PAGE_WINDOW +
  				  (PDC_20621_DIMM_DATA / PDC_20621_PAGE_SIZE),
  	PDC_PAGE_SET		= PDC_DIMM_DATA_STEP / PDC_20621_PAGE_SIZE,
  
  	PDC_CHIP0_OFS		= 0xC0000, /* offset of chip #0 */
  
  	PDC_20621_ERR_MASK	= (1<<19) | (1<<20) | (1<<21) | (1<<22) |
  				  (1<<23),
  
  	board_20621		= 0,	/* FastTrak S150 SX4 */
b2d46b61b   Jeff Garzik   [libata] sata_sx4...
135
136
  	PDC_MASK_INT		= (1 << 10), /* HDMA/ATA mask int */
  	PDC_RESET		= (1 << 11), /* HDMA/ATA reset */
a09060ffe   Jeff Garzik   [libata] sata_sx4...
137
  	PDC_DMA_ENABLE		= (1 << 7),  /* DMA start/stop */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
139
140
  
  	PDC_MAX_HDMA		= 32,
  	PDC_HDMA_Q_MASK		= (PDC_MAX_HDMA - 1),
b2d46b61b   Jeff Garzik   [libata] sata_sx4...
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  	PDC_DIMM0_SPD_DEV_ADDRESS	= 0x50,
  	PDC_DIMM1_SPD_DEV_ADDRESS	= 0x51,
  	PDC_I2C_CONTROL			= 0x48,
  	PDC_I2C_ADDR_DATA		= 0x4C,
  	PDC_DIMM0_CONTROL		= 0x80,
  	PDC_DIMM1_CONTROL		= 0x84,
  	PDC_SDRAM_CONTROL		= 0x88,
  	PDC_I2C_WRITE			= 0,		/* master -> slave */
  	PDC_I2C_READ			= (1 << 6),	/* master <- slave */
  	PDC_I2C_START			= (1 << 7),	/* start I2C proto */
  	PDC_I2C_MASK_INT		= (1 << 5),	/* mask I2C interrupt */
  	PDC_I2C_COMPLETE		= (1 << 16),	/* I2C normal compl. */
  	PDC_I2C_NO_ACK			= (1 << 20),	/* slave no-ack addr */
  	PDC_DIMM_SPD_SUBADDRESS_START	= 0x00,
  	PDC_DIMM_SPD_SUBADDRESS_END	= 0x7F,
  	PDC_DIMM_SPD_ROW_NUM		= 3,
  	PDC_DIMM_SPD_COLUMN_NUM		= 4,
  	PDC_DIMM_SPD_MODULE_ROW		= 5,
  	PDC_DIMM_SPD_TYPE		= 11,
  	PDC_DIMM_SPD_FRESH_RATE		= 12,
  	PDC_DIMM_SPD_BANK_NUM		= 17,
  	PDC_DIMM_SPD_CAS_LATENCY	= 18,
  	PDC_DIMM_SPD_ATTRIBUTE		= 21,
  	PDC_DIMM_SPD_ROW_PRE_CHARGE	= 27,
  	PDC_DIMM_SPD_ROW_ACTIVE_DELAY	= 28,
  	PDC_DIMM_SPD_RAS_CAS_DELAY	= 29,
  	PDC_DIMM_SPD_ACTIVE_PRECHARGE	= 30,
  	PDC_DIMM_SPD_SYSTEM_FREQ	= 126,
  	PDC_CTL_STATUS			= 0x08,
  	PDC_DIMM_WINDOW_CTLR		= 0x0C,
  	PDC_TIME_CONTROL		= 0x3C,
  	PDC_TIME_PERIOD			= 0x40,
  	PDC_TIME_COUNTER		= 0x44,
  	PDC_GENERAL_CTLR		= 0x484,
  	PCI_PLL_INIT			= 0x8A531824,
  	PCI_X_TCOUNT			= 0xEE1E5CFF,
  
  	/* PDC_TIME_CONTROL bits */
  	PDC_TIMER_BUZZER		= (1 << 10),
  	PDC_TIMER_MODE_PERIODIC		= 0,		/* bits 9:8 == 00 */
  	PDC_TIMER_MODE_ONCE		= (1 << 8),	/* bits 9:8 == 01 */
  	PDC_TIMER_ENABLE		= (1 << 7),
  	PDC_TIMER_MASK_INT		= (1 << 5),
  	PDC_TIMER_SEQ_MASK		= 0x1f,		/* SEQ ID for timer */
  	PDC_TIMER_DEFAULT		= PDC_TIMER_MODE_ONCE |
  					  PDC_TIMER_ENABLE |
  					  PDC_TIMER_MASK_INT,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  };
f35b5e7c0   Alexander Beregalov   sata_sx4: speed u...
189
  #define ECC_ERASE_BUF_SZ (128 * 1024)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
191
192
193
194
195
196
197
  
  struct pdc_port_priv {
  	u8			dimm_buf[(ATA_PRD_SZ * ATA_MAX_PRD) + 512];
  	u8			*pkt;
  	dma_addr_t		pkt_dma;
  };
  
  struct pdc_host_priv {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
199
200
201
202
203
204
205
206
  	unsigned int		doing_hdma;
  	unsigned int		hdma_prod;
  	unsigned int		hdma_cons;
  	struct {
  		struct ata_queued_cmd *qc;
  		unsigned int	seq;
  		unsigned long	pkt_ofs;
  	} hdma[32];
  };
5796d1c4c   Jeff Garzik   [libata] Address ...
207
  static int pdc_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
67651ee57   Jeff Garzik   [libata] sata_sx4...
208
209
210
  static void pdc_error_handler(struct ata_port *ap);
  static void pdc_freeze(struct ata_port *ap);
  static void pdc_thaw(struct ata_port *ap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
  static int pdc_port_start(struct ata_port *ap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
057ace5e7   Jeff Garzik   libata: const-ifi...
213
214
  static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
  static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
4447d3515   Tejun Heo   libata: convert t...
215
216
217
  static unsigned int pdc20621_dimm_init(struct ata_host *host);
  static int pdc20621_detect_dimm(struct ata_host *host);
  static unsigned int pdc20621_i2c_read(struct ata_host *host,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
  				      u32 device, u32 subaddr, u32 *pdata);
4447d3515   Tejun Heo   libata: convert t...
219
220
  static int pdc20621_prog_dimm0(struct ata_host *host);
  static unsigned int pdc20621_prog_dimm_global(struct ata_host *host);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  #ifdef ATA_VERBOSE_DEBUG
4447d3515   Tejun Heo   libata: convert t...
222
  static void pdc20621_get_from_dimm(struct ata_host *host,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
224
  				   void *psource, u32 offset, u32 size);
  #endif
4447d3515   Tejun Heo   libata: convert t...
225
  static void pdc20621_put_to_dimm(struct ata_host *host,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
227
  				 void *psource, u32 offset, u32 size);
  static void pdc20621_irq_clear(struct ata_port *ap);
9363c3825   Tejun Heo   libata: rename SF...
228
  static unsigned int pdc20621_qc_issue(struct ata_queued_cmd *qc);
67651ee57   Jeff Garzik   [libata] sata_sx4...
229
230
231
232
  static int pdc_softreset(struct ata_link *link, unsigned int *class,
  			 unsigned long deadline);
  static void pdc_post_internal_cmd(struct ata_queued_cmd *qc);
  static int pdc_check_atapi_dma(struct ata_queued_cmd *qc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233

193515d51   Jeff Garzik   [libata] eliminat...
234
  static struct scsi_host_template pdc_sata_sht = {
68d1d07b5   Tejun Heo   libata: implement...
235
  	ATA_BASE_SHT(DRV_NAME),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  	.sg_tablesize		= LIBATA_MAX_PRD,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
  	.dma_boundary		= ATA_DMA_BOUNDARY,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  };
029cfd6b7   Tejun Heo   libata: implement...
239
240
  /* TODO: inherit from base port_ops after converting to new EH */
  static struct ata_port_operations pdc_20621_ops = {
67651ee57   Jeff Garzik   [libata] sata_sx4...
241
242
243
  	.inherits		= &ata_sff_port_ops,
  
  	.check_atapi_dma	= pdc_check_atapi_dma,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
  	.qc_prep		= pdc20621_qc_prep,
9363c3825   Tejun Heo   libata: rename SF...
245
  	.qc_issue		= pdc20621_qc_issue,
67651ee57   Jeff Garzik   [libata] sata_sx4...
246
247
248
249
250
251
252
  
  	.freeze			= pdc_freeze,
  	.thaw			= pdc_thaw,
  	.softreset		= pdc_softreset,
  	.error_handler		= pdc_error_handler,
  	.lost_interrupt		= ATA_OP_NULL,
  	.post_internal_cmd	= pdc_post_internal_cmd,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
  	.port_start		= pdc_port_start,
67651ee57   Jeff Garzik   [libata] sata_sx4...
254
255
256
257
  
  	.sff_tf_load		= pdc_tf_load_mmio,
  	.sff_exec_command	= pdc_exec_command_mmio,
  	.sff_irq_clear		= pdc20621_irq_clear,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
  };
98ac62def   Arjan van de Ven   [PATCH] mark seve...
259
  static const struct ata_port_info pdc_port_info[] = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
  	/* board_20621 */
  	{
9cbe056f6   Sergei Shtylyov   libata: remove AT...
262
263
  		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_ATAPI |
  				  ATA_FLAG_PIO_POLLING,
14bdef982   Erik Inge Bolsø   [libata] convert ...
264
265
  		.pio_mask	= ATA_PIO4,
  		.mwdma_mask	= ATA_MWDMA2,
469248abf   Jeff Garzik   [libata] Clean up...
266
  		.udma_mask	= ATA_UDMA6,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
268
269
270
  		.port_ops	= &pdc_20621_ops,
  	},
  
  };
3b7d697df   Jeff Garzik   [libata] constify...
271
  static const struct pci_device_id pdc_sata_pci_tbl[] = {
54bb3a94b   Jeff Garzik   [libata] Use new ...
272
  	{ PCI_VDEVICE(PROMISE, 0x6622), board_20621 },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
  	{ }	/* terminate list */
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
276
277
278
279
280
  static struct pci_driver pdc_sata_pci_driver = {
  	.name			= DRV_NAME,
  	.id_table		= pdc_sata_pci_tbl,
  	.probe			= pdc_sata_init_one,
  	.remove			= ata_pci_remove_one,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
282
  static int pdc_port_start(struct ata_port *ap)
  {
cca3974e4   Jeff Garzik   libata: Grand ren...
283
  	struct device *dev = ap->host->dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
  	struct pdc_port_priv *pp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285

24dc5f33e   Tejun Heo   libata: update li...
286
287
288
  	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
  	if (!pp)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289

24dc5f33e   Tejun Heo   libata: update li...
290
291
292
  	pp->pkt = dmam_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL);
  	if (!pp->pkt)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
295
296
  
  	ap->private_data = pp;
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
  static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
5796d1c4c   Jeff Garzik   [libata] Address ...
299
  				   unsigned int portno,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
301
302
303
  					   unsigned int total_len)
  {
  	u32 addr;
  	unsigned int dw = PDC_DIMM_APKT_PRD >> 2;
4ca4e4396   Al Viro   libata annotation...
304
  	__le32 *buf32 = (__le32 *) buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  
  	/* output ATA packet S/G table */
  	addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
  	       (PDC_DIMM_DATA_STEP * portno);
  	VPRINTK("ATA sg addr 0x%x, %d
  ", addr, addr);
  	buf32[dw] = cpu_to_le32(addr);
  	buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT);
  
  	VPRINTK("ATA PSG @ %x == (0x%x, 0x%x)
  ",
  		PDC_20621_DIMM_BASE +
  		       (PDC_DIMM_WINDOW_STEP * portno) +
  		       PDC_DIMM_APKT_PRD,
  		buf32[dw], buf32[dw + 1]);
  }
  
  static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf,
5796d1c4c   Jeff Garzik   [libata] Address ...
323
  				    unsigned int portno,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
326
327
  					    unsigned int total_len)
  {
  	u32 addr;
  	unsigned int dw = PDC_DIMM_HPKT_PRD >> 2;
4ca4e4396   Al Viro   libata annotation...
328
  	__le32 *buf32 = (__le32 *) buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
  
  	/* output Host DMA packet S/G table */
  	addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
  	       (PDC_DIMM_DATA_STEP * portno);
  
  	buf32[dw] = cpu_to_le32(addr);
  	buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT);
  
  	VPRINTK("HOST PSG @ %x == (0x%x, 0x%x)
  ",
  		PDC_20621_DIMM_BASE +
  		       (PDC_DIMM_WINDOW_STEP * portno) +
  		       PDC_DIMM_HPKT_PRD,
  		buf32[dw], buf32[dw + 1]);
  }
  
  static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf,
  					    unsigned int devno, u8 *buf,
  					    unsigned int portno)
  {
  	unsigned int i, dw;
4ca4e4396   Al Viro   libata annotation...
350
  	__le32 *buf32 = (__le32 *) buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
  	u8 dev_reg;
  
  	unsigned int dimm_sg = PDC_20621_DIMM_BASE +
  			       (PDC_DIMM_WINDOW_STEP * portno) +
  			       PDC_DIMM_APKT_PRD;
  	VPRINTK("ENTER, dimm_sg == 0x%x, %d
  ", dimm_sg, dimm_sg);
  
  	i = PDC_DIMM_ATA_PKT;
  
  	/*
  	 * Set up ATA packet
  	 */
  	if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE)))
  		buf[i++] = PDC_PKT_READ;
  	else if (tf->protocol == ATA_PROT_NODATA)
  		buf[i++] = PDC_PKT_NODATA;
  	else
  		buf[i++] = 0;
  	buf[i++] = 0;			/* reserved */
  	buf[i++] = portno + 1;		/* seq. id */
  	buf[i++] = 0xff;		/* delay seq. id */
  
  	/* dimm dma S/G, and next-pkt */
  	dw = i >> 2;
  	if (tf->protocol == ATA_PROT_NODATA)
  		buf32[dw] = 0;
  	else
  		buf32[dw] = cpu_to_le32(dimm_sg);
  	buf32[dw + 1] = 0;
  	i += 8;
  
  	if (devno == 0)
  		dev_reg = ATA_DEVICE_OBS;
  	else
  		dev_reg = ATA_DEVICE_OBS | ATA_DEV1;
  
  	/* select device */
  	buf[i++] = (1 << 5) | PDC_PKT_CLEAR_BSY | ATA_REG_DEVICE;
  	buf[i++] = dev_reg;
  
  	/* device control register */
  	buf[i++] = (1 << 5) | PDC_REG_DEVCTL;
  	buf[i++] = tf->ctl;
  
  	return i;
  }
  
  static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf,
  				     unsigned int portno)
  {
  	unsigned int dw;
4ca4e4396   Al Viro   libata annotation...
403
404
  	u32 tmp;
  	__le32 *buf32 = (__le32 *) buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  
  	unsigned int host_sg = PDC_20621_DIMM_BASE +
  			       (PDC_DIMM_WINDOW_STEP * portno) +
  			       PDC_DIMM_HOST_PRD;
  	unsigned int dimm_sg = PDC_20621_DIMM_BASE +
  			       (PDC_DIMM_WINDOW_STEP * portno) +
  			       PDC_DIMM_HPKT_PRD;
  	VPRINTK("ENTER, dimm_sg == 0x%x, %d
  ", dimm_sg, dimm_sg);
  	VPRINTK("host_sg == 0x%x, %d
  ", host_sg, host_sg);
  
  	dw = PDC_DIMM_HOST_PKT >> 2;
  
  	/*
  	 * Set up Host DMA packet
  	 */
  	if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE)))
  		tmp = PDC_PKT_READ;
  	else
  		tmp = 0;
  	tmp |= ((portno + 1 + 4) << 16);	/* seq. id */
  	tmp |= (0xff << 24);			/* delay seq. id */
  	buf32[dw + 0] = cpu_to_le32(tmp);
  	buf32[dw + 1] = cpu_to_le32(host_sg);
  	buf32[dw + 2] = cpu_to_le32(dimm_sg);
  	buf32[dw + 3] = 0;
  
  	VPRINTK("HOST PKT @ %x == (0x%x 0x%x 0x%x 0x%x)
  ",
  		PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * portno) +
  			PDC_DIMM_HOST_PKT,
  		buf32[dw + 0],
  		buf32[dw + 1],
  		buf32[dw + 2],
  		buf32[dw + 3]);
  }
  
  static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
  {
cedc9a478   Jeff Garzik   libata: fix ATAPI...
445
  	struct scatterlist *sg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
447
  	struct ata_port *ap = qc->ap;
  	struct pdc_port_priv *pp = ap->private_data;
0d5ff5667   Tejun Heo   libata: convert t...
448
449
  	void __iomem *mmio = ap->host->iomap[PDC_MMIO_BAR];
  	void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
  	unsigned int portno = ap->port_no;
ff2aeb1eb   Tejun Heo   libata: convert t...
451
  	unsigned int i, si, idx, total_len = 0, sgt_len;
826cd156d   Al Viro   libata annotations
452
  	__le32 *buf = (__le32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453

beec7dbc6   Tejun Heo   [PATCH] libata: c...
454
  	WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455

44877b4e2   Tejun Heo   libata: s/ap->id/...
456
457
  	VPRINTK("ata%u: ENTER
  ", ap->print_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
460
461
462
463
464
  
  	/* hard-code chip #0 */
  	mmio += PDC_CHIP0_OFS;
  
  	/*
  	 * Build S/G table
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
  	idx = 0;
ff2aeb1eb   Tejun Heo   libata: convert t...
466
  	for_each_sg(qc->sg, sg, qc->n_elem, si) {
cedc9a478   Jeff Garzik   libata: fix ATAPI...
467
468
469
  		buf[idx++] = cpu_to_le32(sg_dma_address(sg));
  		buf[idx++] = cpu_to_le32(sg_dma_len(sg));
  		total_len += sg_dma_len(sg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
  	}
  	buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT);
  	sgt_len = idx * 4;
  
  	/*
  	 * Build ATA, host DMA packets
  	 */
  	pdc20621_host_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len);
  	pdc20621_host_pkt(&qc->tf, &pp->dimm_buf[0], portno);
  
  	pdc20621_ata_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len);
  	i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno);
  
  	if (qc->tf.flags & ATA_TFLAG_LBA48)
  		i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i);
  	else
  		i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i);
  
  	pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i);
  
  	/* copy three S/G tables and two packets to DIMM MMIO window */
  	memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP),
  		    &pp->dimm_buf, PDC_DIMM_HEADER_SZ);
  	memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP) +
  		    PDC_DIMM_HOST_PRD,
  		    &pp->dimm_buf[PDC_DIMM_HEADER_SZ], sgt_len);
  
  	/* force host FIFO dump */
  	writel(0x00000001, mmio + PDC_20621_GENERAL_CTL);
  
  	readl(dimm_mmio);	/* MMIO PCI posting flush */
  
  	VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied
  ", i, sgt_len);
  }
  
  static void pdc20621_nodata_prep(struct ata_queued_cmd *qc)
  {
  	struct ata_port *ap = qc->ap;
  	struct pdc_port_priv *pp = ap->private_data;
0d5ff5667   Tejun Heo   libata: convert t...
510
511
  	void __iomem *mmio = ap->host->iomap[PDC_MMIO_BAR];
  	void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
512
513
  	unsigned int portno = ap->port_no;
  	unsigned int i;
44877b4e2   Tejun Heo   libata: s/ap->id/...
514
515
  	VPRINTK("ata%u: ENTER
  ", ap->print_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
  
  	/* hard-code chip #0 */
  	mmio += PDC_CHIP0_OFS;
  
  	i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno);
  
  	if (qc->tf.flags & ATA_TFLAG_LBA48)
  		i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i);
  	else
  		i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i);
  
  	pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i);
  
  	/* copy three S/G tables and two packets to DIMM MMIO window */
  	memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP),
  		    &pp->dimm_buf, PDC_DIMM_HEADER_SZ);
  
  	/* force host FIFO dump */
  	writel(0x00000001, mmio + PDC_20621_GENERAL_CTL);
  
  	readl(dimm_mmio);	/* MMIO PCI posting flush */
  
  	VPRINTK("ata pkt buf ofs %u, mmio copied
  ", i);
  }
  
  static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
  {
  	switch (qc->tf.protocol) {
  	case ATA_PROT_DMA:
  		pdc20621_dma_prep(qc);
  		break;
  	case ATA_PROT_NODATA:
  		pdc20621_nodata_prep(qc);
  		break;
  	default:
  		break;
  	}
  }
  
  static void __pdc20621_push_hdma(struct ata_queued_cmd *qc,
  				 unsigned int seq,
  				 u32 pkt_ofs)
  {
  	struct ata_port *ap = qc->ap;
cca3974e4   Jeff Garzik   libata: Grand ren...
561
  	struct ata_host *host = ap->host;
0d5ff5667   Tejun Heo   libata: convert t...
562
  	void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
  
  	/* hard-code chip #0 */
  	mmio += PDC_CHIP0_OFS;
  
  	writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
  	readl(mmio + PDC_20621_SEQCTL + (seq * 4));	/* flush */
  
  	writel(pkt_ofs, mmio + PDC_HDMA_PKT_SUBMIT);
  	readl(mmio + PDC_HDMA_PKT_SUBMIT);	/* flush */
  }
  
  static void pdc20621_push_hdma(struct ata_queued_cmd *qc,
  				unsigned int seq,
  				u32 pkt_ofs)
  {
  	struct ata_port *ap = qc->ap;
cca3974e4   Jeff Garzik   libata: Grand ren...
579
  	struct pdc_host_priv *pp = ap->host->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
  	unsigned int idx = pp->hdma_prod & PDC_HDMA_Q_MASK;
  
  	if (!pp->doing_hdma) {
  		__pdc20621_push_hdma(qc, seq, pkt_ofs);
  		pp->doing_hdma = 1;
  		return;
  	}
  
  	pp->hdma[idx].qc = qc;
  	pp->hdma[idx].seq = seq;
  	pp->hdma[idx].pkt_ofs = pkt_ofs;
  	pp->hdma_prod++;
  }
  
  static void pdc20621_pop_hdma(struct ata_queued_cmd *qc)
  {
  	struct ata_port *ap = qc->ap;
cca3974e4   Jeff Garzik   libata: Grand ren...
597
  	struct pdc_host_priv *pp = ap->host->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
  	unsigned int idx = pp->hdma_cons & PDC_HDMA_Q_MASK;
  
  	/* if nothing on queue, we're done */
  	if (pp->hdma_prod == pp->hdma_cons) {
  		pp->doing_hdma = 0;
  		return;
  	}
  
  	__pdc20621_push_hdma(pp->hdma[idx].qc, pp->hdma[idx].seq,
  			     pp->hdma[idx].pkt_ofs);
  	pp->hdma_cons++;
  }
  
  #ifdef ATA_VERBOSE_DEBUG
  static void pdc20621_dump_hdma(struct ata_queued_cmd *qc)
  {
  	struct ata_port *ap = qc->ap;
  	unsigned int port_no = ap->port_no;
0d5ff5667   Tejun Heo   libata: convert t...
616
  	void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
  
  	dimm_mmio += (port_no * PDC_DIMM_WINDOW_STEP);
  	dimm_mmio += PDC_DIMM_HOST_PKT;
  
  	printk(KERN_ERR "HDMA[0] == 0x%08X
  ", readl(dimm_mmio));
  	printk(KERN_ERR "HDMA[1] == 0x%08X
  ", readl(dimm_mmio + 4));
  	printk(KERN_ERR "HDMA[2] == 0x%08X
  ", readl(dimm_mmio + 8));
  	printk(KERN_ERR "HDMA[3] == 0x%08X
  ", readl(dimm_mmio + 12));
  }
  #else
  static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { }
  #endif /* ATA_VERBOSE_DEBUG */
  
  static void pdc20621_packet_start(struct ata_queued_cmd *qc)
  {
  	struct ata_port *ap = qc->ap;
cca3974e4   Jeff Garzik   libata: Grand ren...
637
  	struct ata_host *host = ap->host;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
  	unsigned int port_no = ap->port_no;
0d5ff5667   Tejun Heo   libata: convert t...
639
  	void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
640
641
642
643
644
645
  	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
  	u8 seq = (u8) (port_no + 1);
  	unsigned int port_ofs;
  
  	/* hard-code chip #0 */
  	mmio += PDC_CHIP0_OFS;
44877b4e2   Tejun Heo   libata: s/ap->id/...
646
647
  	VPRINTK("ata%u: ENTER
  ", ap->print_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
  
  	wmb();			/* flush PRD, pkt writes */
  
  	port_ofs = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no);
  
  	/* if writing, we (1) DMA to DIMM, then (2) do ATA command */
  	if (rw && qc->tf.protocol == ATA_PROT_DMA) {
  		seq += 4;
  
  		pdc20621_dump_hdma(qc);
  		pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT);
  		VPRINTK("queued ofs 0x%x (%u), seq %u
  ",
  			port_ofs + PDC_DIMM_HOST_PKT,
  			port_ofs + PDC_DIMM_HOST_PKT,
  			seq);
  	} else {
  		writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
  		readl(mmio + PDC_20621_SEQCTL + (seq * 4));	/* flush */
  
  		writel(port_ofs + PDC_DIMM_ATA_PKT,
0d5ff5667   Tejun Heo   libata: convert t...
669
670
  		       ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
  		readl(ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671
672
673
674
675
676
677
  		VPRINTK("submitted ofs 0x%x (%u), seq %u
  ",
  			port_ofs + PDC_DIMM_ATA_PKT,
  			port_ofs + PDC_DIMM_ATA_PKT,
  			seq);
  	}
  }
9363c3825   Tejun Heo   libata: rename SF...
678
  static unsigned int pdc20621_qc_issue(struct ata_queued_cmd *qc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
680
  {
  	switch (qc->tf.protocol) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
  	case ATA_PROT_NODATA:
19799bfc5   David Milburn   [libata] sata_sx4...
682
683
684
685
  		if (qc->tf.flags & ATA_TFLAG_POLLING)
  			break;
  		/*FALLTHROUGH*/
  	case ATA_PROT_DMA:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
  		pdc20621_packet_start(qc);
  		return 0;
0dc36888d   Tejun Heo   libata: rename AT...
688
  	case ATAPI_PROT_DMA:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
689
690
691
692
693
694
  		BUG();
  		break;
  
  	default:
  		break;
  	}
9363c3825   Tejun Heo   libata: rename SF...
695
  	return ata_sff_qc_issue(qc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
  }
5796d1c4c   Jeff Garzik   [libata] Address ...
697
698
  static inline unsigned int pdc20621_host_intr(struct ata_port *ap,
  					  struct ata_queued_cmd *qc,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
  					  unsigned int doing_hdma,
ea6ba10bb   Jeff Garzik   [libata] __iomem ...
700
  					  void __iomem *mmio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
  {
  	unsigned int port_no = ap->port_no;
  	unsigned int port_ofs =
  		PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no);
  	u8 status;
  	unsigned int handled = 0;
  
  	VPRINTK("ENTER
  ");
  
  	if ((qc->tf.protocol == ATA_PROT_DMA) &&	/* read */
  	    (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
  
  		/* step two - DMA from DIMM to host */
  		if (doing_hdma) {
44877b4e2   Tejun Heo   libata: s/ap->id/...
716
717
  			VPRINTK("ata%u: read hdma, 0x%x 0x%x
  ", ap->print_id,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
718
719
  				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
  			/* get drive status; clear intr; complete txn */
a22e2eb07   Albert Lee   [PATCH] libata: m...
720
721
  			qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
  			ata_qc_complete(qc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
723
724
725
726
727
  			pdc20621_pop_hdma(qc);
  		}
  
  		/* step one - exec ATA command */
  		else {
  			u8 seq = (u8) (port_no + 1 + 4);
44877b4e2   Tejun Heo   libata: s/ap->id/...
728
729
  			VPRINTK("ata%u: read ata, 0x%x 0x%x
  ", ap->print_id,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730
731
732
733
734
735
736
737
738
739
740
741
742
743
  				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
  
  			/* submit hdma pkt */
  			pdc20621_dump_hdma(qc);
  			pdc20621_push_hdma(qc, seq,
  					   port_ofs + PDC_DIMM_HOST_PKT);
  		}
  		handled = 1;
  
  	} else if (qc->tf.protocol == ATA_PROT_DMA) {	/* write */
  
  		/* step one - DMA from host to DIMM */
  		if (doing_hdma) {
  			u8 seq = (u8) (port_no + 1);
44877b4e2   Tejun Heo   libata: s/ap->id/...
744
745
  			VPRINTK("ata%u: write hdma, 0x%x 0x%x
  ", ap->print_id,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
747
748
749
750
751
  				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
  
  			/* submit ata pkt */
  			writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
  			readl(mmio + PDC_20621_SEQCTL + (seq * 4));
  			writel(port_ofs + PDC_DIMM_ATA_PKT,
0d5ff5667   Tejun Heo   libata: convert t...
752
753
  			       ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
  			readl(ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
755
756
757
  		}
  
  		/* step two - execute ATA command */
  		else {
44877b4e2   Tejun Heo   libata: s/ap->id/...
758
759
  			VPRINTK("ata%u: write ata, 0x%x 0x%x
  ", ap->print_id,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
761
  				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
  			/* get drive status; clear intr; complete txn */
a22e2eb07   Albert Lee   [PATCH] libata: m...
762
763
  			qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
  			ata_qc_complete(qc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
766
767
768
769
  			pdc20621_pop_hdma(qc);
  		}
  		handled = 1;
  
  	/* command completion, but no data xfer */
  	} else if (qc->tf.protocol == ATA_PROT_NODATA) {
9363c3825   Tejun Heo   libata: rename SF...
770
  		status = ata_sff_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
772
  		DPRINTK("BUS_NODATA (drv_stat 0x%X)
  ", status);
a22e2eb07   Albert Lee   [PATCH] libata: m...
773
774
  		qc->err_mask |= ac_err_mask(status);
  		ata_qc_complete(qc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
775
776
777
778
779
780
781
782
783
784
785
  		handled = 1;
  
  	} else {
  		ap->stats.idle_irq++;
  	}
  
  	return handled;
  }
  
  static void pdc20621_irq_clear(struct ata_port *ap)
  {
19799bfc5   David Milburn   [libata] sata_sx4...
786
  	ioread8(ap->ioaddr.status_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
787
  }
5796d1c4c   Jeff Garzik   [libata] Address ...
788
  static irqreturn_t pdc20621_interrupt(int irq, void *dev_instance)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
  {
cca3974e4   Jeff Garzik   libata: Grand ren...
790
  	struct ata_host *host = dev_instance;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791
792
793
794
  	struct ata_port *ap;
  	u32 mask = 0;
  	unsigned int i, tmp, port_no;
  	unsigned int handled = 0;
ea6ba10bb   Jeff Garzik   [libata] __iomem ...
795
  	void __iomem *mmio_base;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796
797
798
  
  	VPRINTK("ENTER
  ");
0d5ff5667   Tejun Heo   libata: convert t...
799
  	if (!host || !host->iomap[PDC_MMIO_BAR]) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
801
802
803
  		VPRINTK("QUICK EXIT
  ");
  		return IRQ_NONE;
  	}
0d5ff5667   Tejun Heo   libata: convert t...
804
  	mmio_base = host->iomap[PDC_MMIO_BAR];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
  
  	/* reading should also clear interrupts */
  	mmio_base += PDC_CHIP0_OFS;
  	mask = readl(mmio_base + PDC_20621_SEQMASK);
  	VPRINTK("mask == 0x%x
  ", mask);
  
  	if (mask == 0xffffffff) {
  		VPRINTK("QUICK EXIT 2
  ");
  		return IRQ_NONE;
  	}
  	mask &= 0xffff;		/* only 16 tags possible */
  	if (!mask) {
  		VPRINTK("QUICK EXIT 3
  ");
  		return IRQ_NONE;
  	}
5796d1c4c   Jeff Garzik   [libata] Address ...
823
  	spin_lock(&host->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824

5796d1c4c   Jeff Garzik   [libata] Address ...
825
  	for (i = 1; i < 9; i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826
827
828
  		port_no = i - 1;
  		if (port_no > 3)
  			port_no -= 4;
cca3974e4   Jeff Garzik   libata: Grand ren...
829
  		if (port_no >= host->n_ports)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830
831
  			ap = NULL;
  		else
cca3974e4   Jeff Garzik   libata: Grand ren...
832
  			ap = host->ports[port_no];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833
834
835
  		tmp = mask & (1 << i);
  		VPRINTK("seq %u, port_no %u, ap %p, tmp %x
  ", i, port_no, ap, tmp);
3e4ec3443   Tejun Heo   libata: kill ATA_...
836
  		if (tmp && ap) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
837
  			struct ata_queued_cmd *qc;
9af5c9c97   Tejun Heo   libata-link: intr...
838
  			qc = ata_qc_from_tag(ap, ap->link.active_tag);
e50362ecc   Albert Lee   [PATCH] libata: i...
839
  			if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840
841
842
843
  				handled += pdc20621_host_intr(ap, qc, (i > 4),
  							      mmio_base);
  		}
  	}
5796d1c4c   Jeff Garzik   [libata] Address ...
844
  	spin_unlock(&host->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
846
847
848
849
850
851
852
853
  
  	VPRINTK("mask == 0x%x
  ", mask);
  
  	VPRINTK("EXIT
  ");
  
  	return IRQ_RETVAL(handled);
  }
67651ee57   Jeff Garzik   [libata] sata_sx4...
854
  static void pdc_freeze(struct ata_port *ap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
  {
67651ee57   Jeff Garzik   [libata] sata_sx4...
856
857
  	void __iomem *mmio = ap->ioaddr.cmd_addr;
  	u32 tmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858

67651ee57   Jeff Garzik   [libata] sata_sx4...
859
  	/* FIXME: if all 4 ATA engines are stopped, also stop HDMA engine */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860

67651ee57   Jeff Garzik   [libata] sata_sx4...
861
862
863
864
865
866
  	tmp = readl(mmio + PDC_CTLSTAT);
  	tmp |= PDC_MASK_INT;
  	tmp &= ~PDC_DMA_ENABLE;
  	writel(tmp, mmio + PDC_CTLSTAT);
  	readl(mmio + PDC_CTLSTAT); /* flush */
  }
b8f6153ee   Jeff Garzik   libata: fix EH lo...
867

67651ee57   Jeff Garzik   [libata] sata_sx4...
868
869
870
  static void pdc_thaw(struct ata_port *ap)
  {
  	void __iomem *mmio = ap->ioaddr.cmd_addr;
67651ee57   Jeff Garzik   [libata] sata_sx4...
871
  	u32 tmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
872

67651ee57   Jeff Garzik   [libata] sata_sx4...
873
  	/* FIXME: start HDMA engine, if zero ATA engines running */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
874

19799bfc5   David Milburn   [libata] sata_sx4...
875
876
  	/* clear IRQ */
  	ioread8(ap->ioaddr.status_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
877

67651ee57   Jeff Garzik   [libata] sata_sx4...
878
879
880
881
882
883
  	/* turn IRQ back on */
  	tmp = readl(mmio + PDC_CTLSTAT);
  	tmp &= ~PDC_MASK_INT;
  	writel(tmp, mmio + PDC_CTLSTAT);
  	readl(mmio + PDC_CTLSTAT); /* flush */
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
884

67651ee57   Jeff Garzik   [libata] sata_sx4...
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
  static void pdc_reset_port(struct ata_port *ap)
  {
  	void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT;
  	unsigned int i;
  	u32 tmp;
  
  	/* FIXME: handle HDMA copy engine */
  
  	for (i = 11; i > 0; i--) {
  		tmp = readl(mmio);
  		if (tmp & PDC_RESET)
  			break;
  
  		udelay(100);
  
  		tmp |= PDC_RESET;
  		writel(tmp, mmio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902
  	}
67651ee57   Jeff Garzik   [libata] sata_sx4...
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
  	tmp &= ~PDC_RESET;
  	writel(tmp, mmio);
  	readl(mmio);	/* flush */
  }
  
  static int pdc_softreset(struct ata_link *link, unsigned int *class,
  			 unsigned long deadline)
  {
  	pdc_reset_port(link->ap);
  	return ata_sff_softreset(link, class, deadline);
  }
  
  static void pdc_error_handler(struct ata_port *ap)
  {
  	if (!(ap->pflags & ATA_PFLAG_FROZEN))
  		pdc_reset_port(ap);
fe06e5f9b   Tejun Heo   libata-sff: separ...
919
  	ata_sff_error_handler(ap);
67651ee57   Jeff Garzik   [libata] sata_sx4...
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
  }
  
  static void pdc_post_internal_cmd(struct ata_queued_cmd *qc)
  {
  	struct ata_port *ap = qc->ap;
  
  	/* make DMA engine forget about the failed command */
  	if (qc->flags & ATA_QCFLAG_FAILED)
  		pdc_reset_port(ap);
  }
  
  static int pdc_check_atapi_dma(struct ata_queued_cmd *qc)
  {
  	u8 *scsicmd = qc->scsicmd->cmnd;
  	int pio = 1; /* atapi dma off by default */
  
  	/* Whitelist commands that may use DMA. */
  	switch (scsicmd[0]) {
  	case WRITE_12:
  	case WRITE_10:
  	case WRITE_6:
  	case READ_12:
  	case READ_10:
  	case READ_6:
  	case 0xad: /* READ_DVD_STRUCTURE */
  	case 0xbe: /* READ_CD */
  		pio = 0;
  	}
  	/* -45150 (FFFF4FA2) to -1 (FFFFFFFF) shall use PIO mode */
  	if (scsicmd[0] == WRITE_10) {
  		unsigned int lba =
  			(scsicmd[2] << 24) |
  			(scsicmd[3] << 16) |
  			(scsicmd[4] << 8) |
  			scsicmd[5];
  		if (lba >= 0xFFFF4FA2)
  			pio = 1;
  	}
  	return pio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
959
  }
057ace5e7   Jeff Garzik   libata: const-ifi...
960
  static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961
  {
5796d1c4c   Jeff Garzik   [libata] Address ...
962
  	WARN_ON(tf->protocol == ATA_PROT_DMA ||
19799bfc5   David Milburn   [libata] sata_sx4...
963
  		tf->protocol == ATAPI_PROT_DMA);
9363c3825   Tejun Heo   libata: rename SF...
964
  	ata_sff_tf_load(ap, tf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
965
  }
057ace5e7   Jeff Garzik   libata: const-ifi...
966
  static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
  {
5796d1c4c   Jeff Garzik   [libata] Address ...
968
  	WARN_ON(tf->protocol == ATA_PROT_DMA ||
19799bfc5   David Milburn   [libata] sata_sx4...
969
  		tf->protocol == ATAPI_PROT_DMA);
9363c3825   Tejun Heo   libata: rename SF...
970
  	ata_sff_exec_command(ap, tf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971
  }
0d5ff5667   Tejun Heo   libata: convert t...
972
  static void pdc_sata_setup_port(struct ata_ioports *port, void __iomem *base)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
  {
  	port->cmd_addr		= base;
  	port->data_addr		= base;
  	port->feature_addr	=
  	port->error_addr	= base + 0x4;
  	port->nsect_addr	= base + 0x8;
  	port->lbal_addr		= base + 0xc;
  	port->lbam_addr		= base + 0x10;
  	port->lbah_addr		= base + 0x14;
  	port->device_addr	= base + 0x18;
  	port->command_addr	=
  	port->status_addr	= base + 0x1c;
  	port->altstatus_addr	=
  	port->ctl_addr		= base + 0x38;
  }
  
  
  #ifdef ATA_VERBOSE_DEBUG
4447d3515   Tejun Heo   libata: convert t...
991
  static void pdc20621_get_from_dimm(struct ata_host *host, void *psource,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
992
993
994
995
996
997
  				   u32 offset, u32 size)
  {
  	u32 window_size;
  	u16 idx;
  	u8 page_mask;
  	long dist;
4447d3515   Tejun Heo   libata: convert t...
998
999
  	void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
  	void __iomem *dimm_mmio = host->iomap[PDC_DIMM_BAR];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1000
1001
1002
  
  	/* hard-code chip #0 */
  	mmio += PDC_CHIP0_OFS;
8a60a0712   Jeff Garzik   libata: trim trai...
1003
  	page_mask = 0x00;
5796d1c4c   Jeff Garzik   [libata] Address ...
1004
  	window_size = 0x2000 * 4; /* 32K byte uchar size */
8a60a0712   Jeff Garzik   libata: trim trai...
1005
  	idx = (u16) (offset / window_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1006
1007
1008
1009
1010
1011
1012
1013
  
  	writel(0x01, mmio + PDC_GENERAL_CTLR);
  	readl(mmio + PDC_GENERAL_CTLR);
  	writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
  	readl(mmio + PDC_DIMM_WINDOW_CTLR);
  
  	offset -= (idx * window_size);
  	idx++;
8a60a0712   Jeff Garzik   libata: trim trai...
1014
  	dist = ((long) (window_size - (offset + size))) >= 0 ? size :
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
  		(long) (window_size - offset);
8a60a0712   Jeff Garzik   libata: trim trai...
1016
  	memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1017
  		      dist);
8a60a0712   Jeff Garzik   libata: trim trai...
1018
  	psource += dist;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
1020
1021
1022
1023
1024
  	size -= dist;
  	for (; (long) size >= (long) window_size ;) {
  		writel(0x01, mmio + PDC_GENERAL_CTLR);
  		readl(mmio + PDC_GENERAL_CTLR);
  		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
  		readl(mmio + PDC_DIMM_WINDOW_CTLR);
8a60a0712   Jeff Garzik   libata: trim trai...
1025
  		memcpy_fromio((char *) psource, (char *) (dimm_mmio),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1026
1027
1028
  			      window_size / 4);
  		psource += window_size;
  		size -= window_size;
5796d1c4c   Jeff Garzik   [libata] Address ...
1029
  		idx++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1030
1031
1032
1033
1034
1035
1036
  	}
  
  	if (size) {
  		writel(0x01, mmio + PDC_GENERAL_CTLR);
  		readl(mmio + PDC_GENERAL_CTLR);
  		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
  		readl(mmio + PDC_DIMM_WINDOW_CTLR);
8a60a0712   Jeff Garzik   libata: trim trai...
1037
  		memcpy_fromio((char *) psource, (char *) (dimm_mmio),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1038
1039
1040
1041
  			      size / 4);
  	}
  }
  #endif
4447d3515   Tejun Heo   libata: convert t...
1042
  static void pdc20621_put_to_dimm(struct ata_host *host, void *psource,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1043
1044
1045
1046
1047
1048
  				 u32 offset, u32 size)
  {
  	u32 window_size;
  	u16 idx;
  	u8 page_mask;
  	long dist;
4447d3515   Tejun Heo   libata: convert t...
1049
1050
  	void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
  	void __iomem *dimm_mmio = host->iomap[PDC_DIMM_BAR];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1051

8a60a0712   Jeff Garzik   libata: trim trai...
1052
  	/* hard-code chip #0 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1053
  	mmio += PDC_CHIP0_OFS;
8a60a0712   Jeff Garzik   libata: trim trai...
1054
  	page_mask = 0x00;
5796d1c4c   Jeff Garzik   [libata] Address ...
1055
  	window_size = 0x2000 * 4;       /* 32K byte uchar size */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1056
1057
1058
1059
  	idx = (u16) (offset / window_size);
  
  	writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
  	readl(mmio + PDC_DIMM_WINDOW_CTLR);
8a60a0712   Jeff Garzik   libata: trim trai...
1060
  	offset -= (idx * window_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1061
1062
1063
  	idx++;
  	dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size :
  		(long) (window_size - offset);
a9afd7cd2   Al Viro   [PATCH] iomem ann...
1064
  	memcpy_toio(dimm_mmio + offset / 4, psource, dist);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1065
1066
  	writel(0x01, mmio + PDC_GENERAL_CTLR);
  	readl(mmio + PDC_GENERAL_CTLR);
8a60a0712   Jeff Garzik   libata: trim trai...
1067
  	psource += dist;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1068
1069
1070
1071
  	size -= dist;
  	for (; (long) size >= (long) window_size ;) {
  		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
  		readl(mmio + PDC_DIMM_WINDOW_CTLR);
a9afd7cd2   Al Viro   [PATCH] iomem ann...
1072
  		memcpy_toio(dimm_mmio, psource, window_size / 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1073
1074
1075
1076
  		writel(0x01, mmio + PDC_GENERAL_CTLR);
  		readl(mmio + PDC_GENERAL_CTLR);
  		psource += window_size;
  		size -= window_size;
5796d1c4c   Jeff Garzik   [libata] Address ...
1077
  		idx++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1078
  	}
8a60a0712   Jeff Garzik   libata: trim trai...
1079

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1080
1081
1082
  	if (size) {
  		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
  		readl(mmio + PDC_DIMM_WINDOW_CTLR);
a9afd7cd2   Al Viro   [PATCH] iomem ann...
1083
  		memcpy_toio(dimm_mmio, psource, size / 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1084
1085
1086
1087
  		writel(0x01, mmio + PDC_GENERAL_CTLR);
  		readl(mmio + PDC_GENERAL_CTLR);
  	}
  }
4447d3515   Tejun Heo   libata: convert t...
1088
  static unsigned int pdc20621_i2c_read(struct ata_host *host, u32 device,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1089
1090
  				      u32 subaddr, u32 *pdata)
  {
4447d3515   Tejun Heo   libata: convert t...
1091
  	void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1092
  	u32 i2creg  = 0;
8a60a0712   Jeff Garzik   libata: trim trai...
1093
  	u32 status;
5796d1c4c   Jeff Garzik   [libata] Address ...
1094
  	u32 count = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1095
1096
1097
1098
1099
1100
1101
1102
  
  	/* hard-code chip #0 */
  	mmio += PDC_CHIP0_OFS;
  
  	i2creg |= device << 24;
  	i2creg |= subaddr << 16;
  
  	/* Set the device and subaddress */
b2d46b61b   Jeff Garzik   [libata] sata_sx4...
1103
1104
  	writel(i2creg, mmio + PDC_I2C_ADDR_DATA);
  	readl(mmio + PDC_I2C_ADDR_DATA);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1105
1106
  
  	/* Write Control to perform read operation, mask int */
8a60a0712   Jeff Garzik   libata: trim trai...
1107
  	writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT,
b2d46b61b   Jeff Garzik   [libata] sata_sx4...
1108
  	       mmio + PDC_I2C_CONTROL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1109
1110
  
  	for (count = 0; count <= 1000; count ++) {
b2d46b61b   Jeff Garzik   [libata] sata_sx4...
1111
  		status = readl(mmio + PDC_I2C_CONTROL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1112
  		if (status & PDC_I2C_COMPLETE) {
b2d46b61b   Jeff Garzik   [libata] sata_sx4...
1113
  			status = readl(mmio + PDC_I2C_ADDR_DATA);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1114
1115
1116
1117
1118
1119
  			break;
  		} else if (count == 1000)
  			return 0;
  	}
  
  	*pdata = (status >> 8) & 0x000000ff;
8a60a0712   Jeff Garzik   libata: trim trai...
1120
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1121
  }
4447d3515   Tejun Heo   libata: convert t...
1122
  static int pdc20621_detect_dimm(struct ata_host *host)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1123
  {
5796d1c4c   Jeff Garzik   [libata] Address ...
1124
  	u32 data = 0;
4447d3515   Tejun Heo   libata: convert t...
1125
  	if (pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1126
  			     PDC_DIMM_SPD_SYSTEM_FREQ, &data)) {
5796d1c4c   Jeff Garzik   [libata] Address ...
1127
  		if (data == 100)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1128
  			return 100;
5796d1c4c   Jeff Garzik   [libata] Address ...
1129
  	} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1130
  		return 0;
8a60a0712   Jeff Garzik   libata: trim trai...
1131

4447d3515   Tejun Heo   libata: convert t...
1132
  	if (pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) {
b447916e2   Jeff Garzik   [libata] fix 'if(...
1133
  		if (data <= 0x75)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1134
  			return 133;
5796d1c4c   Jeff Garzik   [libata] Address ...
1135
  	} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1136
  		return 0;
8a60a0712   Jeff Garzik   libata: trim trai...
1137

5796d1c4c   Jeff Garzik   [libata] Address ...
1138
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1139
  }
4447d3515   Tejun Heo   libata: convert t...
1140
  static int pdc20621_prog_dimm0(struct ata_host *host)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1141
1142
1143
  {
  	u32 spd0[50];
  	u32 data = 0;
5796d1c4c   Jeff Garzik   [libata] Address ...
1144
1145
  	int size, i;
  	u8 bdimmsize;
4447d3515   Tejun Heo   libata: convert t...
1146
  	void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1147
1148
1149
1150
  	static const struct {
  		unsigned int reg;
  		unsigned int ofs;
  	} pdc_i2c_read_data [] = {
8a60a0712   Jeff Garzik   libata: trim trai...
1151
  		{ PDC_DIMM_SPD_TYPE, 11 },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1152
  		{ PDC_DIMM_SPD_FRESH_RATE, 12 },
8a60a0712   Jeff Garzik   libata: trim trai...
1153
  		{ PDC_DIMM_SPD_COLUMN_NUM, 4 },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1154
1155
1156
1157
1158
1159
1160
1161
  		{ PDC_DIMM_SPD_ATTRIBUTE, 21 },
  		{ PDC_DIMM_SPD_ROW_NUM, 3 },
  		{ PDC_DIMM_SPD_BANK_NUM, 17 },
  		{ PDC_DIMM_SPD_MODULE_ROW, 5 },
  		{ PDC_DIMM_SPD_ROW_PRE_CHARGE, 27 },
  		{ PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 },
  		{ PDC_DIMM_SPD_RAS_CAS_DELAY, 29 },
  		{ PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 },
8a60a0712   Jeff Garzik   libata: trim trai...
1162
  		{ PDC_DIMM_SPD_CAS_LATENCY, 18 },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1163
1164
1165
1166
  	};
  
  	/* hard-code chip #0 */
  	mmio += PDC_CHIP0_OFS;
5796d1c4c   Jeff Garzik   [libata] Address ...
1167
  	for (i = 0; i < ARRAY_SIZE(pdc_i2c_read_data); i++)
4447d3515   Tejun Heo   libata: convert t...
1168
  		pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
8a60a0712   Jeff Garzik   libata: trim trai...
1169
  				  pdc_i2c_read_data[i].reg,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1170
  				  &spd0[pdc_i2c_read_data[i].ofs]);
8a60a0712   Jeff Garzik   libata: trim trai...
1171

5796d1c4c   Jeff Garzik   [libata] Address ...
1172
1173
  	data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4);
  	data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) |
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1174
  		((((spd0[27] + 9) / 10) - 1) << 8) ;
5796d1c4c   Jeff Garzik   [libata] Address ...
1175
  	data |= (((((spd0[29] > spd0[28])
8a60a0712   Jeff Garzik   libata: trim trai...
1176
  		    ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10;
5796d1c4c   Jeff Garzik   [libata] Address ...
1177
  	data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12;
8a60a0712   Jeff Garzik   libata: trim trai...
1178

5796d1c4c   Jeff Garzik   [libata] Address ...
1179
  	if (spd0[18] & 0x08)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180
  		data |= ((0x03) << 14);
5796d1c4c   Jeff Garzik   [libata] Address ...
1181
  	else if (spd0[18] & 0x04)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1182
  		data |= ((0x02) << 14);
5796d1c4c   Jeff Garzik   [libata] Address ...
1183
  	else if (spd0[18] & 0x01)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1184
  		data |= ((0x01) << 14);
5796d1c4c   Jeff Garzik   [libata] Address ...
1185
  	else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186
  		data |= (0 << 14);
5796d1c4c   Jeff Garzik   [libata] Address ...
1187
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1188
1189
1190
  	   Calculate the size of bDIMMSize (power of 2) and
  	   merge the DIMM size by program start/end address.
  	*/
5796d1c4c   Jeff Garzik   [libata] Address ...
1191
1192
1193
1194
  	bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3;
  	size = (1 << bdimmsize) >> 20;	/* size = xxx(MB) */
  	data |= (((size / 16) - 1) << 16);
  	data |= (0 << 23);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195
  	data |= 8;
5796d1c4c   Jeff Garzik   [libata] Address ...
1196
  	writel(data, mmio + PDC_DIMM0_CONTROL);
b2d46b61b   Jeff Garzik   [libata] sata_sx4...
1197
  	readl(mmio + PDC_DIMM0_CONTROL);
5796d1c4c   Jeff Garzik   [libata] Address ...
1198
  	return size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1199
  }
4447d3515   Tejun Heo   libata: convert t...
1200
  static unsigned int pdc20621_prog_dimm_global(struct ata_host *host)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1201
1202
  {
  	u32 data, spd0;
0d5ff5667   Tejun Heo   libata: convert t...
1203
  	int error, i;
4447d3515   Tejun Heo   libata: convert t...
1204
  	void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205
1206
  
  	/* hard-code chip #0 */
5796d1c4c   Jeff Garzik   [libata] Address ...
1207
  	mmio += PDC_CHIP0_OFS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1208

5796d1c4c   Jeff Garzik   [libata] Address ...
1209
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1210
1211
1212
1213
1214
  	  Set To Default : DIMM Module Global Control Register (0x022259F1)
  	  DIMM Arbitration Disable (bit 20)
  	  DIMM Data/Control Output Driving Selection (bit12 - bit15)
  	  Refresh Enable (bit 17)
  	*/
8a60a0712   Jeff Garzik   libata: trim trai...
1215
  	data = 0x022259F1;
b2d46b61b   Jeff Garzik   [libata] sata_sx4...
1216
1217
  	writel(data, mmio + PDC_SDRAM_CONTROL);
  	readl(mmio + PDC_SDRAM_CONTROL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1218
1219
  
  	/* Turn on for ECC */
4447d3515   Tejun Heo   libata: convert t...
1220
  	pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1221
1222
1223
  			  PDC_DIMM_SPD_TYPE, &spd0);
  	if (spd0 == 0x02) {
  		data |= (0x01 << 16);
b2d46b61b   Jeff Garzik   [libata] sata_sx4...
1224
1225
  		writel(data, mmio + PDC_SDRAM_CONTROL);
  		readl(mmio + PDC_SDRAM_CONTROL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226
1227
  		printk(KERN_ERR "Local DIMM ECC Enabled
  ");
5796d1c4c   Jeff Garzik   [libata] Address ...
1228
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1229

5796d1c4c   Jeff Garzik   [libata] Address ...
1230
1231
1232
1233
  	/* DIMM Initialization Select/Enable (bit 18/19) */
  	data &= (~(1<<18));
  	data |= (1<<19);
  	writel(data, mmio + PDC_SDRAM_CONTROL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1234

5796d1c4c   Jeff Garzik   [libata] Address ...
1235
1236
  	error = 1;
  	for (i = 1; i <= 10; i++) {   /* polling ~5 secs */
b2d46b61b   Jeff Garzik   [libata] sata_sx4...
1237
  		data = readl(mmio + PDC_SDRAM_CONTROL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1238
  		if (!(data & (1<<19))) {
5796d1c4c   Jeff Garzik   [libata] Address ...
1239
1240
  			error = 0;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1241
1242
  		}
  		msleep(i*100);
5796d1c4c   Jeff Garzik   [libata] Address ...
1243
1244
  	}
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1245
  }
8a60a0712   Jeff Garzik   libata: trim trai...
1246

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1247

4447d3515   Tejun Heo   libata: convert t...
1248
  static unsigned int pdc20621_dimm_init(struct ata_host *host)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1249
  {
8a60a0712   Jeff Garzik   libata: trim trai...
1250
  	int speed, size, length;
5796d1c4c   Jeff Garzik   [libata] Address ...
1251
  	u32 addr, spd0, pci_status;
5796d1c4c   Jeff Garzik   [libata] Address ...
1252
1253
1254
1255
1256
  	u32 time_period = 0;
  	u32 tcount = 0;
  	u32 ticks = 0;
  	u32 clock = 0;
  	u32 fparam = 0;
4447d3515   Tejun Heo   libata: convert t...
1257
  	void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1258
1259
  
  	/* hard-code chip #0 */
5796d1c4c   Jeff Garzik   [libata] Address ...
1260
  	mmio += PDC_CHIP0_OFS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
  
  	/* Initialize PLL based upon PCI Bus Frequency */
  
  	/* Initialize Time Period Register */
  	writel(0xffffffff, mmio + PDC_TIME_PERIOD);
  	time_period = readl(mmio + PDC_TIME_PERIOD);
  	VPRINTK("Time Period Register (0x40): 0x%x
  ", time_period);
  
  	/* Enable timer */
b2d46b61b   Jeff Garzik   [libata] sata_sx4...
1271
  	writel(PDC_TIMER_DEFAULT, mmio + PDC_TIME_CONTROL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1272
1273
1274
1275
  	readl(mmio + PDC_TIME_CONTROL);
  
  	/* Wait 3 seconds */
  	msleep(3000);
8a60a0712   Jeff Garzik   libata: trim trai...
1276
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1277
1278
1279
1280
1281
1282
1283
  	   When timer is enabled, counter is decreased every internal
  	   clock cycle.
  	*/
  
  	tcount = readl(mmio + PDC_TIME_COUNTER);
  	VPRINTK("Time Counter Register (0x44): 0x%x
  ", tcount);
8a60a0712   Jeff Garzik   libata: trim trai...
1284
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1285
1286
1287
  	   If SX4 is on PCI-X bus, after 3 seconds, the timer counter
  	   register should be >= (0xffffffff - 3x10^8).
  	*/
b447916e2   Jeff Garzik   [libata] fix 'if(...
1288
  	if (tcount >= PCI_X_TCOUNT) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1289
1290
1291
  		ticks = (time_period - tcount);
  		VPRINTK("Num counters 0x%x (%d)
  ", ticks, ticks);
8a60a0712   Jeff Garzik   libata: trim trai...
1292

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1293
1294
1295
  		clock = (ticks / 300000);
  		VPRINTK("10 * Internal clk = 0x%x (%d)
  ", clock, clock);
8a60a0712   Jeff Garzik   libata: trim trai...
1296

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1297
1298
1299
1300
1301
1302
1303
1304
  		clock = (clock * 33);
  		VPRINTK("10 * Internal clk * 33 = 0x%x (%d)
  ", clock, clock);
  
  		/* PLL F Param (bit 22:16) */
  		fparam = (1400000 / clock) - 2;
  		VPRINTK("PLL F Param: 0x%x (%d)
  ", fparam, fparam);
8a60a0712   Jeff Garzik   libata: trim trai...
1305

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
  		/* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */
  		pci_status = (0x8a001824 | (fparam << 16));
  	} else
  		pci_status = PCI_PLL_INIT;
  
  	/* Initialize PLL. */
  	VPRINTK("pci_status: 0x%x
  ", pci_status);
  	writel(pci_status, mmio + PDC_CTL_STATUS);
  	readl(mmio + PDC_CTL_STATUS);
8a60a0712   Jeff Garzik   libata: trim trai...
1316
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1317
1318
1319
  	   Read SPD of DIMM by I2C interface,
  	   and program the DIMM Module Controller.
  	*/
4447d3515   Tejun Heo   libata: convert t...
1320
  	if (!(speed = pdc20621_detect_dimm(host))) {
8a60a0712   Jeff Garzik   libata: trim trai...
1321
1322
  		printk(KERN_ERR "Detect Local DIMM Fail
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1323
  		return 1;	/* DIMM error */
5796d1c4c   Jeff Garzik   [libata] Address ...
1324
1325
1326
  	}
  	VPRINTK("Local DIMM Speed = %d
  ", speed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1327

5796d1c4c   Jeff Garzik   [libata] Address ...
1328
  	/* Programming DIMM0 Module Control Register (index_CID0:80h) */
4447d3515   Tejun Heo   libata: convert t...
1329
  	size = pdc20621_prog_dimm0(host);
5796d1c4c   Jeff Garzik   [libata] Address ...
1330
1331
  	VPRINTK("Local DIMM Size = %dMB
  ", size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1332

5796d1c4c   Jeff Garzik   [libata] Address ...
1333
  	/* Programming DIMM Module Global Control Register (index_CID0:88h) */
4447d3515   Tejun Heo   libata: convert t...
1334
  	if (pdc20621_prog_dimm_global(host)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1335
1336
1337
  		printk(KERN_ERR "Programming DIMM Module Global Control Register Fail
  ");
  		return 1;
5796d1c4c   Jeff Garzik   [libata] Address ...
1338
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1339
1340
1341
  
  #ifdef ATA_VERBOSE_DEBUG
  	{
5796d1c4c   Jeff Garzik   [libata] Address ...
1342
1343
1344
1345
1346
1347
  		u8 test_parttern1[40] =
  			{0x55,0xAA,'P','r','o','m','i','s','e',' ',
  			'N','o','t',' ','Y','e','t',' ',
  			'D','e','f','i','n','e','d',' ',
  			'1','.','1','0',
  			'9','8','0','3','1','6','1','2',0,0};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1348
  		u8 test_parttern2[40] = {0};
5796d1c4c   Jeff Garzik   [libata] Address ...
1349
1350
  		pdc20621_put_to_dimm(host, test_parttern2, 0x10040, 40);
  		pdc20621_put_to_dimm(host, test_parttern2, 0x40, 40);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1351

5796d1c4c   Jeff Garzik   [libata] Address ...
1352
1353
  		pdc20621_put_to_dimm(host, test_parttern1, 0x10040, 40);
  		pdc20621_get_from_dimm(host, test_parttern2, 0x40, 40);
8a60a0712   Jeff Garzik   libata: trim trai...
1354
1355
  		printk(KERN_ERR "%x, %x, %s
  ", test_parttern2[0],
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1356
  		       test_parttern2[1], &(test_parttern2[2]));
5796d1c4c   Jeff Garzik   [libata] Address ...
1357
  		pdc20621_get_from_dimm(host, test_parttern2, 0x10040,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1358
  				       40);
8a60a0712   Jeff Garzik   libata: trim trai...
1359
1360
  		printk(KERN_ERR "%x, %x, %s
  ", test_parttern2[0],
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1361
  		       test_parttern2[1], &(test_parttern2[2]));
5796d1c4c   Jeff Garzik   [libata] Address ...
1362
1363
  		pdc20621_put_to_dimm(host, test_parttern1, 0x40, 40);
  		pdc20621_get_from_dimm(host, test_parttern2, 0x40, 40);
8a60a0712   Jeff Garzik   libata: trim trai...
1364
1365
  		printk(KERN_ERR "%x, %x, %s
  ", test_parttern2[0],
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1366
1367
1368
1369
1370
  		       test_parttern2[1], &(test_parttern2[2]));
  	}
  #endif
  
  	/* ECC initiliazation. */
4447d3515   Tejun Heo   libata: convert t...
1371
  	pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1372
1373
  			  PDC_DIMM_SPD_TYPE, &spd0);
  	if (spd0 == 0x02) {
f35b5e7c0   Alexander Beregalov   sata_sx4: speed u...
1374
  		void *buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1375
1376
1377
1378
  		VPRINTK("Start ECC initialization
  ");
  		addr = 0;
  		length = size * 1024 * 1024;
f35b5e7c0   Alexander Beregalov   sata_sx4: speed u...
1379
  		buf = kzalloc(ECC_ERASE_BUF_SZ, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1380
  		while (addr < length) {
f35b5e7c0   Alexander Beregalov   sata_sx4: speed u...
1381
1382
1383
  			pdc20621_put_to_dimm(host, buf, addr,
  					     ECC_ERASE_BUF_SZ);
  			addr += ECC_ERASE_BUF_SZ;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1384
  		}
f35b5e7c0   Alexander Beregalov   sata_sx4: speed u...
1385
  		kfree(buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1386
1387
1388
1389
1390
  		VPRINTK("Finish ECC initialization
  ");
  	}
  	return 0;
  }
4447d3515   Tejun Heo   libata: convert t...
1391
  static void pdc_20621_init(struct ata_host *host)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1392
1393
  {
  	u32 tmp;
4447d3515   Tejun Heo   libata: convert t...
1394
  	void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
  
  	/* hard-code chip #0 */
  	mmio += PDC_CHIP0_OFS;
  
  	/*
  	 * Select page 0x40 for our 32k DIMM window
  	 */
  	tmp = readl(mmio + PDC_20621_DIMM_WINDOW) & 0xffff0000;
  	tmp |= PDC_PAGE_WINDOW;	/* page 40h; arbitrarily selected */
  	writel(tmp, mmio + PDC_20621_DIMM_WINDOW);
  
  	/*
  	 * Reset Host DMA
  	 */
  	tmp = readl(mmio + PDC_HDMA_CTLSTAT);
  	tmp |= PDC_RESET;
  	writel(tmp, mmio + PDC_HDMA_CTLSTAT);
  	readl(mmio + PDC_HDMA_CTLSTAT);		/* flush */
  
  	udelay(10);
  
  	tmp = readl(mmio + PDC_HDMA_CTLSTAT);
  	tmp &= ~PDC_RESET;
  	writel(tmp, mmio + PDC_HDMA_CTLSTAT);
  	readl(mmio + PDC_HDMA_CTLSTAT);		/* flush */
  }
5796d1c4c   Jeff Garzik   [libata] Address ...
1421
1422
  static int pdc_sata_init_one(struct pci_dev *pdev,
  			     const struct pci_device_id *ent)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1423
  {
4447d3515   Tejun Heo   libata: convert t...
1424
1425
1426
  	const struct ata_port_info *ppi[] =
  		{ &pdc_port_info[ent->driver_data], NULL };
  	struct ata_host *host;
24dc5f33e   Tejun Heo   libata: update li...
1427
  	struct pdc_host_priv *hpriv;
cbcdd8759   Tejun Heo   libata: implement...
1428
  	int i, rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1429

06296a1e6   Joe Perches   ata: Add and use ...
1430
  	ata_print_version_once(&pdev->dev, DRV_VERSION);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1431

4447d3515   Tejun Heo   libata: convert t...
1432
1433
1434
1435
1436
1437
1438
1439
1440
  	/* allocate host */
  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 4);
  	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
  	if (!host || !hpriv)
  		return -ENOMEM;
  
  	host->private_data = hpriv;
  
  	/* acquire resources and fill host */
24dc5f33e   Tejun Heo   libata: update li...
1441
  	rc = pcim_enable_device(pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1442
1443
  	if (rc)
  		return rc;
0d5ff5667   Tejun Heo   libata: convert t...
1444
1445
1446
  	rc = pcim_iomap_regions(pdev, (1 << PDC_MMIO_BAR) | (1 << PDC_DIMM_BAR),
  				DRV_NAME);
  	if (rc == -EBUSY)
24dc5f33e   Tejun Heo   libata: update li...
1447
  		pcim_pin_device(pdev);
0d5ff5667   Tejun Heo   libata: convert t...
1448
  	if (rc)
24dc5f33e   Tejun Heo   libata: update li...
1449
  		return rc;
4447d3515   Tejun Heo   libata: convert t...
1450
  	host->iomap = pcim_iomap_table(pdev);
cbcdd8759   Tejun Heo   libata: implement...
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
  	for (i = 0; i < 4; i++) {
  		struct ata_port *ap = host->ports[i];
  		void __iomem *base = host->iomap[PDC_MMIO_BAR] + PDC_CHIP0_OFS;
  		unsigned int offset = 0x200 + i * 0x80;
  
  		pdc_sata_setup_port(&ap->ioaddr, base + offset);
  
  		ata_port_pbar_desc(ap, PDC_MMIO_BAR, -1, "mmio");
  		ata_port_pbar_desc(ap, PDC_DIMM_BAR, -1, "dimm");
  		ata_port_pbar_desc(ap, PDC_MMIO_BAR, offset, "port");
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1462

4447d3515   Tejun Heo   libata: convert t...
1463
  	/* configure and activate */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1464
1465
  	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
  	if (rc)
24dc5f33e   Tejun Heo   libata: update li...
1466
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1467
1468
  	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
  	if (rc)
24dc5f33e   Tejun Heo   libata: update li...
1469
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1470

4447d3515   Tejun Heo   libata: convert t...
1471
  	if (pdc20621_dimm_init(host))
24dc5f33e   Tejun Heo   libata: update li...
1472
  		return -ENOMEM;
4447d3515   Tejun Heo   libata: convert t...
1473
  	pdc_20621_init(host);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1474
1475
  
  	pci_set_master(pdev);
4447d3515   Tejun Heo   libata: convert t...
1476
1477
  	return ata_host_activate(host, pdev->irq, pdc20621_interrupt,
  				 IRQF_SHARED, &pdc_sata_sht);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
1479
1480
1481
1482
  }
  
  
  static int __init pdc_sata_init(void)
  {
b7887196e   Pavel Roskin   [PATCH] libata: r...
1483
  	return pci_register_driver(&pdc_sata_pci_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
  }
  
  
  static void __exit pdc_sata_exit(void)
  {
  	pci_unregister_driver(&pdc_sata_pci_driver);
  }
  
  
  MODULE_AUTHOR("Jeff Garzik");
  MODULE_DESCRIPTION("Promise SATA low-level driver");
  MODULE_LICENSE("GPL");
  MODULE_DEVICE_TABLE(pci, pdc_sata_pci_tbl);
  MODULE_VERSION(DRV_VERSION);
  
  module_init(pdc_sata_init);
  module_exit(pdc_sata_exit);