Blame view

drivers/ata/pdc_adma.c 16.7 KB
edea3ab58   Mark Lord   libata: add new d...
1
2
3
4
5
6
7
  /*
   *  pdc_adma.c - Pacific Digital Corporation ADMA
   *
   *  Maintained by:  Mark Lord <mlord@pobox.com>
   *
   *  Copyright 2005 Mark Lord
   *
68399bb50   Jeff Garzik   [libata pdc_adma]...
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
   *  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.*
edea3ab58   Mark Lord   libata: add new d...
25
   *
edea3ab58   Mark Lord   libata: add new d...
26
27
28
29
30
31
32
33
34
35
36
   *
   *  Supports ATA disks in single-packet ADMA mode.
   *  Uses PIO for everything else.
   *
   *  TODO:  Use ADMA transfers for ATAPI devices, when possible.
   *  This requires careful attention to a number of quirks of the chip.
   *
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
37
  #include <linux/gfp.h>
edea3ab58   Mark Lord   libata: add new d...
38
39
40
41
42
  #include <linux/pci.h>
  #include <linux/init.h>
  #include <linux/blkdev.h>
  #include <linux/delay.h>
  #include <linux/interrupt.h>
a9524a76f   Jeff Garzik   [libata] use dev_...
43
  #include <linux/device.h>
edea3ab58   Mark Lord   libata: add new d...
44
  #include <scsi/scsi_host.h>
edea3ab58   Mark Lord   libata: add new d...
45
46
47
  #include <linux/libata.h>
  
  #define DRV_NAME	"pdc_adma"
2a3103ce4   Jeff Garzik   [libata] Bump dri...
48
  #define DRV_VERSION	"1.0"
edea3ab58   Mark Lord   libata: add new d...
49
50
  
  /* macro to calculate base address for ATA regs */
5796d1c4c   Jeff Garzik   [libata] Address ...
51
  #define ADMA_ATA_REGS(base, port_no)	((base) + ((port_no) * 0x40))
edea3ab58   Mark Lord   libata: add new d...
52
53
  
  /* macro to calculate base address for ADMA regs */
5796d1c4c   Jeff Garzik   [libata] Address ...
54
  #define ADMA_REGS(base, port_no)	((base) + 0x80 + ((port_no) * 0x20))
0d5ff5667   Tejun Heo   libata: convert t...
55

5d728824e   Tejun Heo   libata: convert t...
56
57
58
  /* macro to obtain addresses from ata_port */
  #define ADMA_PORT_REGS(ap) \
  	ADMA_REGS((ap)->host->iomap[ADMA_MMIO_BAR], ap->port_no)
edea3ab58   Mark Lord   libata: add new d...
59
60
  
  enum {
0d5ff5667   Tejun Heo   libata: convert t...
61
  	ADMA_MMIO_BAR		= 4,
edea3ab58   Mark Lord   libata: add new d...
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  	ADMA_PORTS		= 2,
  	ADMA_CPB_BYTES		= 40,
  	ADMA_PRD_BYTES		= LIBATA_MAX_PRD * 16,
  	ADMA_PKT_BYTES		= ADMA_CPB_BYTES + ADMA_PRD_BYTES,
  
  	ADMA_DMA_BOUNDARY	= 0xffffffff,
  
  	/* global register offsets */
  	ADMA_MODE_LOCK		= 0x00c7,
  
  	/* per-channel register offsets */
  	ADMA_CONTROL		= 0x0000, /* ADMA control */
  	ADMA_STATUS		= 0x0002, /* ADMA status */
  	ADMA_CPB_COUNT		= 0x0004, /* CPB count */
  	ADMA_CPB_CURRENT	= 0x000c, /* current CPB address */
  	ADMA_CPB_NEXT		= 0x000c, /* next CPB address */
  	ADMA_CPB_LOOKUP		= 0x0010, /* CPB lookup table */
  	ADMA_FIFO_IN		= 0x0014, /* input FIFO threshold */
  	ADMA_FIFO_OUT		= 0x0016, /* output FIFO threshold */
  
  	/* ADMA_CONTROL register bits */
  	aNIEN			= (1 << 8), /* irq mask: 1==masked */
  	aGO			= (1 << 7), /* packet trigger ("Go!") */
  	aRSTADM			= (1 << 5), /* ADMA logic reset */
edea3ab58   Mark Lord   libata: add new d...
86
87
88
89
90
91
92
93
94
  	aPIOMD4			= 0x0003,   /* PIO mode 4 */
  
  	/* ADMA_STATUS register bits */
  	aPSD			= (1 << 6),
  	aUIRQ			= (1 << 4),
  	aPERR			= (1 << 0),
  
  	/* CPB bits */
  	cDONE			= (1 << 0),
640fdb504   Jeff Garzik   [libata] pdc_adma...
95
  	cATERR			= (1 << 3),
edea3ab58   Mark Lord   libata: add new d...
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  	cVLD			= (1 << 0),
  	cDAT			= (1 << 2),
  	cIEN			= (1 << 3),
  
  	/* PRD bits */
  	pORD			= (1 << 4),
  	pDIRO			= (1 << 5),
  	pEND			= (1 << 7),
  
  	/* ATA register flags */
  	rIGN			= (1 << 5),
  	rEND			= (1 << 7),
  
  	/* ATA register addresses */
  	ADMA_REGS_CONTROL	= 0x0e,
  	ADMA_REGS_SECTOR_COUNT	= 0x12,
  	ADMA_REGS_LBA_LOW	= 0x13,
  	ADMA_REGS_LBA_MID	= 0x14,
  	ADMA_REGS_LBA_HIGH	= 0x15,
  	ADMA_REGS_DEVICE	= 0x16,
  	ADMA_REGS_COMMAND	= 0x17,
  
  	/* PCI device IDs */
  	board_1841_idx		= 0,	/* ADMA 2-port controller */
  };
  
  typedef enum { adma_state_idle, adma_state_pkt, adma_state_mmio } adma_state_t;
  
  struct adma_port_priv {
  	u8			*pkt;
  	dma_addr_t		pkt_dma;
  	adma_state_t		state;
  };
5796d1c4c   Jeff Garzik   [libata] Address ...
129
  static int adma_ata_init_one(struct pci_dev *pdev,
edea3ab58   Mark Lord   libata: add new d...
130
  				const struct pci_device_id *ent);
edea3ab58   Mark Lord   libata: add new d...
131
  static int adma_port_start(struct ata_port *ap);
edea3ab58   Mark Lord   libata: add new d...
132
  static void adma_port_stop(struct ata_port *ap);
edea3ab58   Mark Lord   libata: add new d...
133
  static void adma_qc_prep(struct ata_queued_cmd *qc);
9a3d9eb01   Tejun Heo   [PATCH] libata: r...
134
  static unsigned int adma_qc_issue(struct ata_queued_cmd *qc);
edea3ab58   Mark Lord   libata: add new d...
135
  static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
640fdb504   Jeff Garzik   [libata] pdc_adma...
136
137
  static void adma_freeze(struct ata_port *ap);
  static void adma_thaw(struct ata_port *ap);
a1efdaba2   Tejun Heo   libata: make rese...
138
  static int adma_prereset(struct ata_link *link, unsigned long deadline);
edea3ab58   Mark Lord   libata: add new d...
139

193515d51   Jeff Garzik   [libata] eliminat...
140
  static struct scsi_host_template adma_ata_sht = {
68d1d07b5   Tejun Heo   libata: implement...
141
  	ATA_BASE_SHT(DRV_NAME),
edea3ab58   Mark Lord   libata: add new d...
142
  	.sg_tablesize		= LIBATA_MAX_PRD,
49de0ac82   Jeff Garzik   [libata] pdc_adma...
143
  	.dma_boundary		= ADMA_DMA_BOUNDARY,
edea3ab58   Mark Lord   libata: add new d...
144
  };
029cfd6b7   Tejun Heo   libata: implement...
145
  static struct ata_port_operations adma_ata_ops = {
b0316b15a   Tejun Heo   pdc_adma: inherit...
146
  	.inherits		= &ata_sff_port_ops,
c96f1732e   Alan Cox   [libata] Improve ...
147
  	.lost_interrupt		= ATA_OP_NULL,
029cfd6b7   Tejun Heo   libata: implement...
148
  	.check_atapi_dma	= adma_check_atapi_dma,
edea3ab58   Mark Lord   libata: add new d...
149
150
  	.qc_prep		= adma_qc_prep,
  	.qc_issue		= adma_qc_issue,
029cfd6b7   Tejun Heo   libata: implement...
151

640fdb504   Jeff Garzik   [libata] pdc_adma...
152
153
  	.freeze			= adma_freeze,
  	.thaw			= adma_thaw,
a1efdaba2   Tejun Heo   libata: make rese...
154
  	.prereset		= adma_prereset,
029cfd6b7   Tejun Heo   libata: implement...
155

edea3ab58   Mark Lord   libata: add new d...
156
157
  	.port_start		= adma_port_start,
  	.port_stop		= adma_port_stop,
edea3ab58   Mark Lord   libata: add new d...
158
159
160
161
162
  };
  
  static struct ata_port_info adma_port_info[] = {
  	/* board_1841_idx */
  	{
640fdb504   Jeff Garzik   [libata] pdc_adma...
163
  		.flags		= ATA_FLAG_SLAVE_POSS |
51704c609   Albert Lee   [PATCH] libata: U...
164
165
  				  ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
  				  ATA_FLAG_PIO_POLLING,
14bdef982   Erik Inge Bolsø   [libata] convert ...
166
  		.pio_mask	= ATA_PIO4_ONLY,
bf6263a85   Jeff Garzik   [libata] Use ATA_...
167
  		.udma_mask	= ATA_UDMA4,
edea3ab58   Mark Lord   libata: add new d...
168
169
170
  		.port_ops	= &adma_ata_ops,
  	},
  };
3b7d697df   Jeff Garzik   [libata] constify...
171
  static const struct pci_device_id adma_ata_pci_tbl[] = {
54bb3a94b   Jeff Garzik   [libata] Use new ...
172
  	{ PCI_VDEVICE(PDC, 0x1841), board_1841_idx },
edea3ab58   Mark Lord   libata: add new d...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  
  	{ }	/* terminate list */
  };
  
  static struct pci_driver adma_ata_pci_driver = {
  	.name			= DRV_NAME,
  	.id_table		= adma_ata_pci_tbl,
  	.probe			= adma_ata_init_one,
  	.remove			= ata_pci_remove_one,
  };
  
  static int adma_check_atapi_dma(struct ata_queued_cmd *qc)
  {
  	return 1;	/* ATAPI DMA not yet supported */
  }
5d728824e   Tejun Heo   libata: convert t...
188
  static void adma_reset_engine(struct ata_port *ap)
edea3ab58   Mark Lord   libata: add new d...
189
  {
5d728824e   Tejun Heo   libata: convert t...
190
  	void __iomem *chan = ADMA_PORT_REGS(ap);
edea3ab58   Mark Lord   libata: add new d...
191
192
193
194
195
196
197
198
199
200
  	/* reset ADMA to idle state */
  	writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
  	udelay(2);
  	writew(aPIOMD4, chan + ADMA_CONTROL);
  	udelay(2);
  }
  
  static void adma_reinit_engine(struct ata_port *ap)
  {
  	struct adma_port_priv *pp = ap->private_data;
5d728824e   Tejun Heo   libata: convert t...
201
  	void __iomem *chan = ADMA_PORT_REGS(ap);
edea3ab58   Mark Lord   libata: add new d...
202
203
  
  	/* mask/clear ATA interrupts */
0d5ff5667   Tejun Heo   libata: convert t...
204
  	writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
9363c3825   Tejun Heo   libata: rename SF...
205
  	ata_sff_check_status(ap);
edea3ab58   Mark Lord   libata: add new d...
206
207
  
  	/* reset the ADMA engine */
5d728824e   Tejun Heo   libata: convert t...
208
  	adma_reset_engine(ap);
edea3ab58   Mark Lord   libata: add new d...
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  
  	/* set in-FIFO threshold to 0x100 */
  	writew(0x100, chan + ADMA_FIFO_IN);
  
  	/* set CPB pointer */
  	writel((u32)pp->pkt_dma, chan + ADMA_CPB_NEXT);
  
  	/* set out-FIFO threshold to 0x100 */
  	writew(0x100, chan + ADMA_FIFO_OUT);
  
  	/* set CPB count */
  	writew(1, chan + ADMA_CPB_COUNT);
  
  	/* read/discard ADMA status */
  	readb(chan + ADMA_STATUS);
  }
  
  static inline void adma_enter_reg_mode(struct ata_port *ap)
  {
5d728824e   Tejun Heo   libata: convert t...
228
  	void __iomem *chan = ADMA_PORT_REGS(ap);
edea3ab58   Mark Lord   libata: add new d...
229
230
231
232
  
  	writew(aPIOMD4, chan + ADMA_CONTROL);
  	readb(chan + ADMA_STATUS);	/* flush */
  }
640fdb504   Jeff Garzik   [libata] pdc_adma...
233
  static void adma_freeze(struct ata_port *ap)
edea3ab58   Mark Lord   libata: add new d...
234
  {
640fdb504   Jeff Garzik   [libata] pdc_adma...
235
236
237
238
  	void __iomem *chan = ADMA_PORT_REGS(ap);
  
  	/* mask/clear ATA interrupts */
  	writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
9363c3825   Tejun Heo   libata: rename SF...
239
  	ata_sff_check_status(ap);
640fdb504   Jeff Garzik   [libata] pdc_adma...
240
241
242
243
244
245
246
  
  	/* reset ADMA to idle state */
  	writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
  	udelay(2);
  	writew(aPIOMD4 | aNIEN, chan + ADMA_CONTROL);
  	udelay(2);
  }
edea3ab58   Mark Lord   libata: add new d...
247

640fdb504   Jeff Garzik   [libata] pdc_adma...
248
249
  static void adma_thaw(struct ata_port *ap)
  {
edea3ab58   Mark Lord   libata: add new d...
250
  	adma_reinit_engine(ap);
edea3ab58   Mark Lord   libata: add new d...
251
  }
0260731f0   Tejun Heo   libata-link: link...
252
  static int adma_prereset(struct ata_link *link, unsigned long deadline)
edea3ab58   Mark Lord   libata: add new d...
253
  {
0260731f0   Tejun Heo   libata-link: link...
254
  	struct ata_port *ap = link->ap;
edea3ab58   Mark Lord   libata: add new d...
255
256
257
258
259
  	struct adma_port_priv *pp = ap->private_data;
  
  	if (pp->state != adma_state_idle) /* healthy paranoia */
  		pp->state = adma_state_mmio;
  	adma_reinit_engine(ap);
640fdb504   Jeff Garzik   [libata] pdc_adma...
260

9363c3825   Tejun Heo   libata: rename SF...
261
  	return ata_sff_prereset(link, deadline);
640fdb504   Jeff Garzik   [libata] pdc_adma...
262
  }
edea3ab58   Mark Lord   libata: add new d...
263
264
  static int adma_fill_sg(struct ata_queued_cmd *qc)
  {
972c26bdd   Jeff Garzik   libata: add ata_s...
265
  	struct scatterlist *sg;
edea3ab58   Mark Lord   libata: add new d...
266
267
  	struct ata_port *ap = qc->ap;
  	struct adma_port_priv *pp = ap->private_data;
3be6cbd73   Jeff Garzik   [libata] kill ata...
268
  	u8  *buf = pp->pkt, *last_buf = NULL;
972c26bdd   Jeff Garzik   libata: add ata_s...
269
  	int i = (2 + buf[3]) * 8;
edea3ab58   Mark Lord   libata: add new d...
270
  	u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0);
ff2aeb1eb   Tejun Heo   libata: convert t...
271
  	unsigned int si;
edea3ab58   Mark Lord   libata: add new d...
272

ff2aeb1eb   Tejun Heo   libata: convert t...
273
  	for_each_sg(qc->sg, sg, qc->n_elem, si) {
edea3ab58   Mark Lord   libata: add new d...
274
275
276
277
278
279
280
281
282
283
  		u32 addr;
  		u32 len;
  
  		addr = (u32)sg_dma_address(sg);
  		*(__le32 *)(buf + i) = cpu_to_le32(addr);
  		i += 4;
  
  		len = sg_dma_len(sg) >> 3;
  		*(__le32 *)(buf + i) = cpu_to_le32(len);
  		i += 4;
3be6cbd73   Jeff Garzik   [libata] kill ata...
284
  		last_buf = &buf[i];
edea3ab58   Mark Lord   libata: add new d...
285
286
287
288
  		buf[i++] = pFLAGS;
  		buf[i++] = qc->dev->dma_mode & 0xf;
  		buf[i++] = 0;	/* pPKLW */
  		buf[i++] = 0;	/* reserved */
5796d1c4c   Jeff Garzik   [libata] Address ...
289
290
  		*(__le32 *)(buf + i) =
  			(pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4);
edea3ab58   Mark Lord   libata: add new d...
291
  		i += 4;
db7f44d96   Alan Cox   [PATCH] libata: m...
292
293
  		VPRINTK("PRD[%u] = (0x%lX, 0x%X)
  ", i/4,
edea3ab58   Mark Lord   libata: add new d...
294
295
  					(unsigned long)addr, len);
  	}
3be6cbd73   Jeff Garzik   [libata] kill ata...
296
297
298
  
  	if (likely(last_buf))
  		*last_buf |= pEND;
edea3ab58   Mark Lord   libata: add new d...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
  	return i;
  }
  
  static void adma_qc_prep(struct ata_queued_cmd *qc)
  {
  	struct adma_port_priv *pp = qc->ap->private_data;
  	u8  *buf = pp->pkt;
  	u32 pkt_dma = (u32)pp->pkt_dma;
  	int i = 0;
  
  	VPRINTK("ENTER
  ");
  
  	adma_enter_reg_mode(qc->ap);
f47451c45   Tejun Heo   libata-sff: ata_s...
313
  	if (qc->tf.protocol != ATA_PROT_DMA)
edea3ab58   Mark Lord   libata: add new d...
314
  		return;
edea3ab58   Mark Lord   libata: add new d...
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
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
  
  	buf[i++] = 0;	/* Response flags */
  	buf[i++] = 0;	/* reserved */
  	buf[i++] = cVLD | cDAT | cIEN;
  	i++;		/* cLEN, gets filled in below */
  
  	*(__le32 *)(buf+i) = cpu_to_le32(pkt_dma);	/* cNCPB */
  	i += 4;		/* cNCPB */
  	i += 4;		/* cPRD, gets filled in below */
  
  	buf[i++] = 0;	/* reserved */
  	buf[i++] = 0;	/* reserved */
  	buf[i++] = 0;	/* reserved */
  	buf[i++] = 0;	/* reserved */
  
  	/* ATA registers; must be a multiple of 4 */
  	buf[i++] = qc->tf.device;
  	buf[i++] = ADMA_REGS_DEVICE;
  	if ((qc->tf.flags & ATA_TFLAG_LBA48)) {
  		buf[i++] = qc->tf.hob_nsect;
  		buf[i++] = ADMA_REGS_SECTOR_COUNT;
  		buf[i++] = qc->tf.hob_lbal;
  		buf[i++] = ADMA_REGS_LBA_LOW;
  		buf[i++] = qc->tf.hob_lbam;
  		buf[i++] = ADMA_REGS_LBA_MID;
  		buf[i++] = qc->tf.hob_lbah;
  		buf[i++] = ADMA_REGS_LBA_HIGH;
  	}
  	buf[i++] = qc->tf.nsect;
  	buf[i++] = ADMA_REGS_SECTOR_COUNT;
  	buf[i++] = qc->tf.lbal;
  	buf[i++] = ADMA_REGS_LBA_LOW;
  	buf[i++] = qc->tf.lbam;
  	buf[i++] = ADMA_REGS_LBA_MID;
  	buf[i++] = qc->tf.lbah;
  	buf[i++] = ADMA_REGS_LBA_HIGH;
  	buf[i++] = 0;
  	buf[i++] = ADMA_REGS_CONTROL;
  	buf[i++] = rIGN;
  	buf[i++] = 0;
  	buf[i++] = qc->tf.command;
  	buf[i++] = ADMA_REGS_COMMAND | rEND;
  
  	buf[3] = (i >> 3) - 2;				/* cLEN */
  	*(__le32 *)(buf+8) = cpu_to_le32(pkt_dma + i);	/* cPRD */
  
  	i = adma_fill_sg(qc);
  	wmb();	/* flush PRDs and pkt to memory */
  #if 0
  	/* dump out CPB + PRDs for debug */
  	{
  		int j, len = 0;
  		static char obuf[2048];
  		for (j = 0; j < i; ++j) {
  			len += sprintf(obuf+len, "%02x ", buf[j]);
  			if ((j & 7) == 7) {
  				printk("%s
  ", obuf);
  				len = 0;
  			}
  		}
  		if (len)
  			printk("%s
  ", obuf);
  	}
  #endif
  }
  
  static inline void adma_packet_start(struct ata_queued_cmd *qc)
  {
  	struct ata_port *ap = qc->ap;
5d728824e   Tejun Heo   libata: convert t...
386
  	void __iomem *chan = ADMA_PORT_REGS(ap);
edea3ab58   Mark Lord   libata: add new d...
387
388
389
390
391
  
  	VPRINTK("ENTER, ap %p
  ", ap);
  
  	/* fire up the ADMA engine */
68399bb50   Jeff Garzik   [libata pdc_adma]...
392
  	writew(aPIOMD4 | aGO, chan + ADMA_CONTROL);
edea3ab58   Mark Lord   libata: add new d...
393
  }
9a3d9eb01   Tejun Heo   [PATCH] libata: r...
394
  static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)
edea3ab58   Mark Lord   libata: add new d...
395
396
397
398
399
400
401
402
  {
  	struct adma_port_priv *pp = qc->ap->private_data;
  
  	switch (qc->tf.protocol) {
  	case ATA_PROT_DMA:
  		pp->state = adma_state_pkt;
  		adma_packet_start(qc);
  		return 0;
0dc36888d   Tejun Heo   libata: rename AT...
403
  	case ATAPI_PROT_DMA:
edea3ab58   Mark Lord   libata: add new d...
404
405
406
407
408
409
410
411
  		BUG();
  		break;
  
  	default:
  		break;
  	}
  
  	pp->state = adma_state_mmio;
9363c3825   Tejun Heo   libata: rename SF...
412
  	return ata_sff_qc_issue(qc);
edea3ab58   Mark Lord   libata: add new d...
413
  }
cca3974e4   Jeff Garzik   libata: Grand ren...
414
  static inline unsigned int adma_intr_pkt(struct ata_host *host)
edea3ab58   Mark Lord   libata: add new d...
415
416
  {
  	unsigned int handled = 0, port_no;
edea3ab58   Mark Lord   libata: add new d...
417

cca3974e4   Jeff Garzik   libata: Grand ren...
418
419
  	for (port_no = 0; port_no < host->n_ports; ++port_no) {
  		struct ata_port *ap = host->ports[port_no];
edea3ab58   Mark Lord   libata: add new d...
420
421
  		struct adma_port_priv *pp;
  		struct ata_queued_cmd *qc;
5d728824e   Tejun Heo   libata: convert t...
422
  		void __iomem *chan = ADMA_PORT_REGS(ap);
a7dac447b   Jeff Garzik   [libata] change a...
423
  		u8 status = readb(chan + ADMA_STATUS);
edea3ab58   Mark Lord   libata: add new d...
424
425
426
427
428
  
  		if (status == 0)
  			continue;
  		handled = 1;
  		adma_enter_reg_mode(ap);
edea3ab58   Mark Lord   libata: add new d...
429
430
431
  		pp = ap->private_data;
  		if (!pp || pp->state != adma_state_pkt)
  			continue;
9af5c9c97   Tejun Heo   libata-link: intr...
432
  		qc = ata_qc_from_tag(ap, ap->link.active_tag);
94ec1ef1c   Jeff Garzik   [libata pdc_adma]...
433
  		if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
640fdb504   Jeff Garzik   [libata] pdc_adma...
434
435
436
  			if (status & aPERR)
  				qc->err_mask |= AC_ERR_HOST_BUS;
  			else if ((status & (aPSD | aUIRQ)))
a22e2eb07   Albert Lee   [PATCH] libata: m...
437
  				qc->err_mask |= AC_ERR_OTHER;
640fdb504   Jeff Garzik   [libata] pdc_adma...
438
439
440
  
  			if (pp->pkt[0] & cATERR)
  				qc->err_mask |= AC_ERR_DEV;
a21a84a37   Jeff Garzik   [libata pdc_adma]...
441
  			else if (pp->pkt[0] != cDONE)
a22e2eb07   Albert Lee   [PATCH] libata: m...
442
  				qc->err_mask |= AC_ERR_OTHER;
a7dac447b   Jeff Garzik   [libata] change a...
443

640fdb504   Jeff Garzik   [libata] pdc_adma...
444
445
446
  			if (!qc->err_mask)
  				ata_qc_complete(qc);
  			else {
9af5c9c97   Tejun Heo   libata-link: intr...
447
  				struct ata_eh_info *ehi = &ap->link.eh_info;
640fdb504   Jeff Garzik   [libata] pdc_adma...
448
449
450
451
452
453
454
455
456
457
458
  				ata_ehi_clear_desc(ehi);
  				ata_ehi_push_desc(ehi,
  					"ADMA-status 0x%02X", status);
  				ata_ehi_push_desc(ehi,
  					"pkt[0] 0x%02X", pp->pkt[0]);
  
  				if (qc->err_mask == AC_ERR_DEV)
  					ata_port_abort(ap);
  				else
  					ata_port_freeze(ap);
  			}
a21a84a37   Jeff Garzik   [libata pdc_adma]...
459
  		}
edea3ab58   Mark Lord   libata: add new d...
460
461
462
  	}
  	return handled;
  }
cca3974e4   Jeff Garzik   libata: Grand ren...
463
  static inline unsigned int adma_intr_mmio(struct ata_host *host)
edea3ab58   Mark Lord   libata: add new d...
464
465
  {
  	unsigned int handled = 0, port_no;
cca3974e4   Jeff Garzik   libata: Grand ren...
466
  	for (port_no = 0; port_no < host->n_ports; ++port_no) {
3e4ec3443   Tejun Heo   libata: kill ATA_...
467
468
469
470
471
472
473
474
475
476
477
478
  		struct ata_port *ap = host->ports[port_no];
  		struct adma_port_priv *pp = ap->private_data;
  		struct ata_queued_cmd *qc;
  
  		if (!pp || pp->state != adma_state_mmio)
  			continue;
  		qc = ata_qc_from_tag(ap, ap->link.active_tag);
  		if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
  
  			/* check main status, clearing INTRQ */
  			u8 status = ata_sff_check_status(ap);
  			if ((status & ATA_BUSY))
edea3ab58   Mark Lord   libata: add new d...
479
  				continue;
3e4ec3443   Tejun Heo   libata: kill ATA_...
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
  			DPRINTK("ata%u: protocol %d (dev_stat 0x%X)
  ",
  				ap->print_id, qc->tf.protocol, status);
  
  			/* complete taskfile transaction */
  			pp->state = adma_state_idle;
  			qc->err_mask |= ac_err_mask(status);
  			if (!qc->err_mask)
  				ata_qc_complete(qc);
  			else {
  				struct ata_eh_info *ehi = &ap->link.eh_info;
  				ata_ehi_clear_desc(ehi);
  				ata_ehi_push_desc(ehi, "status 0x%02X", status);
  
  				if (qc->err_mask == AC_ERR_DEV)
  					ata_port_abort(ap);
  				else
  					ata_port_freeze(ap);
edea3ab58   Mark Lord   libata: add new d...
498
  			}
3e4ec3443   Tejun Heo   libata: kill ATA_...
499
  			handled = 1;
edea3ab58   Mark Lord   libata: add new d...
500
501
502
503
  		}
  	}
  	return handled;
  }
7d12e780e   David Howells   IRQ: Maintain reg...
504
  static irqreturn_t adma_intr(int irq, void *dev_instance)
edea3ab58   Mark Lord   libata: add new d...
505
  {
cca3974e4   Jeff Garzik   libata: Grand ren...
506
  	struct ata_host *host = dev_instance;
edea3ab58   Mark Lord   libata: add new d...
507
508
509
510
  	unsigned int handled = 0;
  
  	VPRINTK("ENTER
  ");
cca3974e4   Jeff Garzik   libata: Grand ren...
511
512
513
  	spin_lock(&host->lock);
  	handled  = adma_intr_pkt(host) | adma_intr_mmio(host);
  	spin_unlock(&host->lock);
edea3ab58   Mark Lord   libata: add new d...
514
515
516
517
518
519
  
  	VPRINTK("EXIT
  ");
  
  	return IRQ_RETVAL(handled);
  }
0d5ff5667   Tejun Heo   libata: convert t...
520
  static void adma_ata_setup_port(struct ata_ioports *port, void __iomem *base)
edea3ab58   Mark Lord   libata: add new d...
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
  {
  	port->cmd_addr		=
  	port->data_addr		= base + 0x000;
  	port->error_addr	=
  	port->feature_addr	= base + 0x004;
  	port->nsect_addr	= base + 0x008;
  	port->lbal_addr		= base + 0x00c;
  	port->lbam_addr		= base + 0x010;
  	port->lbah_addr		= base + 0x014;
  	port->device_addr	= base + 0x018;
  	port->status_addr	=
  	port->command_addr	= base + 0x01c;
  	port->altstatus_addr	=
  	port->ctl_addr		= base + 0x038;
  }
  
  static int adma_port_start(struct ata_port *ap)
  {
cca3974e4   Jeff Garzik   libata: Grand ren...
539
  	struct device *dev = ap->host->dev;
edea3ab58   Mark Lord   libata: add new d...
540
  	struct adma_port_priv *pp;
edea3ab58   Mark Lord   libata: add new d...
541

edea3ab58   Mark Lord   libata: add new d...
542
  	adma_enter_reg_mode(ap);
24dc5f33e   Tejun Heo   libata: update li...
543
  	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
edea3ab58   Mark Lord   libata: add new d...
544
  	if (!pp)
24dc5f33e   Tejun Heo   libata: update li...
545
546
547
  		return -ENOMEM;
  	pp->pkt = dmam_alloc_coherent(dev, ADMA_PKT_BYTES, &pp->pkt_dma,
  				      GFP_KERNEL);
edea3ab58   Mark Lord   libata: add new d...
548
  	if (!pp->pkt)
24dc5f33e   Tejun Heo   libata: update li...
549
  		return -ENOMEM;
edea3ab58   Mark Lord   libata: add new d...
550
551
  	/* paranoia? */
  	if ((pp->pkt_dma & 7) != 0) {
5796d1c4c   Jeff Garzik   [libata] Address ...
552
553
  		printk(KERN_ERR "bad alignment for pp->pkt_dma: %08x
  ",
edea3ab58   Mark Lord   libata: add new d...
554
  						(u32)pp->pkt_dma);
24dc5f33e   Tejun Heo   libata: update li...
555
  		return -ENOMEM;
edea3ab58   Mark Lord   libata: add new d...
556
557
558
559
560
  	}
  	memset(pp->pkt, 0, ADMA_PKT_BYTES);
  	ap->private_data = pp;
  	adma_reinit_engine(ap);
  	return 0;
edea3ab58   Mark Lord   libata: add new d...
561
562
563
564
  }
  
  static void adma_port_stop(struct ata_port *ap)
  {
5d728824e   Tejun Heo   libata: convert t...
565
  	adma_reset_engine(ap);
edea3ab58   Mark Lord   libata: add new d...
566
  }
5d728824e   Tejun Heo   libata: convert t...
567
  static void adma_host_init(struct ata_host *host, unsigned int chip_id)
edea3ab58   Mark Lord   libata: add new d...
568
569
  {
  	unsigned int port_no;
edea3ab58   Mark Lord   libata: add new d...
570
571
  
  	/* enable/lock aGO operation */
5d728824e   Tejun Heo   libata: convert t...
572
  	writeb(7, host->iomap[ADMA_MMIO_BAR] + ADMA_MODE_LOCK);
edea3ab58   Mark Lord   libata: add new d...
573
574
575
  
  	/* reset the ADMA logic */
  	for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
5d728824e   Tejun Heo   libata: convert t...
576
  		adma_reset_engine(host->ports[port_no]);
edea3ab58   Mark Lord   libata: add new d...
577
578
579
580
581
  }
  
  static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
  {
  	int rc;
284901a90   Yang Hongyang   dma-mapping: repl...
582
  	rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
edea3ab58   Mark Lord   libata: add new d...
583
  	if (rc) {
a9524a76f   Jeff Garzik   [libata] use dev_...
584
585
586
  		dev_printk(KERN_ERR, &pdev->dev,
  			"32-bit DMA enable failed
  ");
edea3ab58   Mark Lord   libata: add new d...
587
588
  		return rc;
  	}
284901a90   Yang Hongyang   dma-mapping: repl...
589
  	rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
edea3ab58   Mark Lord   libata: add new d...
590
  	if (rc) {
a9524a76f   Jeff Garzik   [libata] use dev_...
591
592
593
  		dev_printk(KERN_ERR, &pdev->dev,
  			"32-bit consistent DMA enable failed
  ");
edea3ab58   Mark Lord   libata: add new d...
594
595
596
597
598
599
  		return rc;
  	}
  	return 0;
  }
  
  static int adma_ata_init_one(struct pci_dev *pdev,
0d5ff5667   Tejun Heo   libata: convert t...
600
  			     const struct pci_device_id *ent)
edea3ab58   Mark Lord   libata: add new d...
601
602
  {
  	static int printed_version;
edea3ab58   Mark Lord   libata: add new d...
603
  	unsigned int board_idx = (unsigned int) ent->driver_data;
5d728824e   Tejun Heo   libata: convert t...
604
605
606
  	const struct ata_port_info *ppi[] = { &adma_port_info[board_idx], NULL };
  	struct ata_host *host;
  	void __iomem *mmio_base;
edea3ab58   Mark Lord   libata: add new d...
607
608
609
  	int rc, port_no;
  
  	if (!printed_version++)
a9524a76f   Jeff Garzik   [libata] use dev_...
610
611
  		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "
  ");
edea3ab58   Mark Lord   libata: add new d...
612

5d728824e   Tejun Heo   libata: convert t...
613
614
615
616
617
618
  	/* alloc host */
  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, ADMA_PORTS);
  	if (!host)
  		return -ENOMEM;
  
  	/* acquire resources and fill host */
24dc5f33e   Tejun Heo   libata: update li...
619
  	rc = pcim_enable_device(pdev);
edea3ab58   Mark Lord   libata: add new d...
620
621
  	if (rc)
  		return rc;
24dc5f33e   Tejun Heo   libata: update li...
622
623
  	if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0)
  		return -ENODEV;
edea3ab58   Mark Lord   libata: add new d...
624

0d5ff5667   Tejun Heo   libata: convert t...
625
626
627
  	rc = pcim_iomap_regions(pdev, 1 << ADMA_MMIO_BAR, DRV_NAME);
  	if (rc)
  		return rc;
5d728824e   Tejun Heo   libata: convert t...
628
629
  	host->iomap = pcim_iomap_table(pdev);
  	mmio_base = host->iomap[ADMA_MMIO_BAR];
edea3ab58   Mark Lord   libata: add new d...
630
631
632
  
  	rc = adma_set_dma_masks(pdev, mmio_base);
  	if (rc)
24dc5f33e   Tejun Heo   libata: update li...
633
  		return rc;
edea3ab58   Mark Lord   libata: add new d...
634

cbcdd8759   Tejun Heo   libata: implement...
635
636
637
638
639
640
641
642
643
644
  	for (port_no = 0; port_no < ADMA_PORTS; ++port_no) {
  		struct ata_port *ap = host->ports[port_no];
  		void __iomem *port_base = ADMA_ATA_REGS(mmio_base, port_no);
  		unsigned int offset = port_base - mmio_base;
  
  		adma_ata_setup_port(&ap->ioaddr, port_base);
  
  		ata_port_pbar_desc(ap, ADMA_MMIO_BAR, -1, "mmio");
  		ata_port_pbar_desc(ap, ADMA_MMIO_BAR, offset, "port");
  	}
edea3ab58   Mark Lord   libata: add new d...
645
646
  
  	/* initialize adapter */
5d728824e   Tejun Heo   libata: convert t...
647
  	adma_host_init(host, board_idx);
edea3ab58   Mark Lord   libata: add new d...
648

5d728824e   Tejun Heo   libata: convert t...
649
650
651
  	pci_set_master(pdev);
  	return ata_host_activate(host, pdev->irq, adma_intr, IRQF_SHARED,
  				 &adma_ata_sht);
edea3ab58   Mark Lord   libata: add new d...
652
653
654
655
  }
  
  static int __init adma_ata_init(void)
  {
b7887196e   Pavel Roskin   [PATCH] libata: r...
656
  	return pci_register_driver(&adma_ata_pci_driver);
edea3ab58   Mark Lord   libata: add new d...
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
  }
  
  static void __exit adma_ata_exit(void)
  {
  	pci_unregister_driver(&adma_ata_pci_driver);
  }
  
  MODULE_AUTHOR("Mark Lord");
  MODULE_DESCRIPTION("Pacific Digital Corporation ADMA low-level driver");
  MODULE_LICENSE("GPL");
  MODULE_DEVICE_TABLE(pci, adma_ata_pci_tbl);
  MODULE_VERSION(DRV_VERSION);
  
  module_init(adma_ata_init);
  module_exit(adma_ata_exit);