Blame view

drivers/ata/pdc_adma.c 16.5 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 */
  	{
9cbe056f6   Sergei Shtylyov   libata: remove AT...
163
  		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_POLLING,
14bdef982   Erik Inge Bolsø   [libata] convert ...
164
  		.pio_mask	= ATA_PIO4_ONLY,
bf6263a85   Jeff Garzik   [libata] Use ATA_...
165
  		.udma_mask	= ATA_UDMA4,
edea3ab58   Mark Lord   libata: add new d...
166
167
168
  		.port_ops	= &adma_ata_ops,
  	},
  };
3b7d697df   Jeff Garzik   [libata] constify...
169
  static const struct pci_device_id adma_ata_pci_tbl[] = {
54bb3a94b   Jeff Garzik   [libata] Use new ...
170
  	{ PCI_VDEVICE(PDC, 0x1841), board_1841_idx },
edea3ab58   Mark Lord   libata: add new d...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  
  	{ }	/* 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...
186
  static void adma_reset_engine(struct ata_port *ap)
edea3ab58   Mark Lord   libata: add new d...
187
  {
5d728824e   Tejun Heo   libata: convert t...
188
  	void __iomem *chan = ADMA_PORT_REGS(ap);
edea3ab58   Mark Lord   libata: add new d...
189
190
191
192
193
194
195
196
197
198
  	/* 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...
199
  	void __iomem *chan = ADMA_PORT_REGS(ap);
edea3ab58   Mark Lord   libata: add new d...
200
201
  
  	/* mask/clear ATA interrupts */
0d5ff5667   Tejun Heo   libata: convert t...
202
  	writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
9363c3825   Tejun Heo   libata: rename SF...
203
  	ata_sff_check_status(ap);
edea3ab58   Mark Lord   libata: add new d...
204
205
  
  	/* reset the ADMA engine */
5d728824e   Tejun Heo   libata: convert t...
206
  	adma_reset_engine(ap);
edea3ab58   Mark Lord   libata: add new d...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  
  	/* 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...
226
  	void __iomem *chan = ADMA_PORT_REGS(ap);
edea3ab58   Mark Lord   libata: add new d...
227
228
229
230
  
  	writew(aPIOMD4, chan + ADMA_CONTROL);
  	readb(chan + ADMA_STATUS);	/* flush */
  }
640fdb504   Jeff Garzik   [libata] pdc_adma...
231
  static void adma_freeze(struct ata_port *ap)
edea3ab58   Mark Lord   libata: add new d...
232
  {
640fdb504   Jeff Garzik   [libata] pdc_adma...
233
234
235
236
  	void __iomem *chan = ADMA_PORT_REGS(ap);
  
  	/* mask/clear ATA interrupts */
  	writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
9363c3825   Tejun Heo   libata: rename SF...
237
  	ata_sff_check_status(ap);
640fdb504   Jeff Garzik   [libata] pdc_adma...
238
239
240
241
242
243
244
  
  	/* 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...
245

640fdb504   Jeff Garzik   [libata] pdc_adma...
246
247
  static void adma_thaw(struct ata_port *ap)
  {
edea3ab58   Mark Lord   libata: add new d...
248
  	adma_reinit_engine(ap);
edea3ab58   Mark Lord   libata: add new d...
249
  }
0260731f0   Tejun Heo   libata-link: link...
250
  static int adma_prereset(struct ata_link *link, unsigned long deadline)
edea3ab58   Mark Lord   libata: add new d...
251
  {
0260731f0   Tejun Heo   libata-link: link...
252
  	struct ata_port *ap = link->ap;
edea3ab58   Mark Lord   libata: add new d...
253
254
255
256
257
  	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...
258

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

ff2aeb1eb   Tejun Heo   libata: convert t...
271
  	for_each_sg(qc->sg, sg, qc->n_elem, si) {
edea3ab58   Mark Lord   libata: add new d...
272
273
274
275
276
277
278
279
280
281
  		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...
282
  		last_buf = &buf[i];
edea3ab58   Mark Lord   libata: add new d...
283
284
285
286
  		buf[i++] = pFLAGS;
  		buf[i++] = qc->dev->dma_mode & 0xf;
  		buf[i++] = 0;	/* pPKLW */
  		buf[i++] = 0;	/* reserved */
5796d1c4c   Jeff Garzik   [libata] Address ...
287
288
  		*(__le32 *)(buf + i) =
  			(pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4);
edea3ab58   Mark Lord   libata: add new d...
289
  		i += 4;
db7f44d96   Alan Cox   [PATCH] libata: m...
290
291
  		VPRINTK("PRD[%u] = (0x%lX, 0x%X)
  ", i/4,
edea3ab58   Mark Lord   libata: add new d...
292
293
  					(unsigned long)addr, len);
  	}
3be6cbd73   Jeff Garzik   [libata] kill ata...
294
295
296
  
  	if (likely(last_buf))
  		*last_buf |= pEND;
edea3ab58   Mark Lord   libata: add new d...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
  	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...
311
  	if (qc->tf.protocol != ATA_PROT_DMA)
edea3ab58   Mark Lord   libata: add new d...
312
  		return;
edea3ab58   Mark Lord   libata: add new d...
313
314
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
  
  	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...
384
  	void __iomem *chan = ADMA_PORT_REGS(ap);
edea3ab58   Mark Lord   libata: add new d...
385
386
387
388
389
  
  	VPRINTK("ENTER, ap %p
  ", ap);
  
  	/* fire up the ADMA engine */
68399bb50   Jeff Garzik   [libata pdc_adma]...
390
  	writew(aPIOMD4 | aGO, chan + ADMA_CONTROL);
edea3ab58   Mark Lord   libata: add new d...
391
  }
9a3d9eb01   Tejun Heo   [PATCH] libata: r...
392
  static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)
edea3ab58   Mark Lord   libata: add new d...
393
394
395
396
397
398
399
400
  {
  	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...
401
  	case ATAPI_PROT_DMA:
edea3ab58   Mark Lord   libata: add new d...
402
403
404
405
406
407
408
409
  		BUG();
  		break;
  
  	default:
  		break;
  	}
  
  	pp->state = adma_state_mmio;
9363c3825   Tejun Heo   libata: rename SF...
410
  	return ata_sff_qc_issue(qc);
edea3ab58   Mark Lord   libata: add new d...
411
  }
cca3974e4   Jeff Garzik   libata: Grand ren...
412
  static inline unsigned int adma_intr_pkt(struct ata_host *host)
edea3ab58   Mark Lord   libata: add new d...
413
414
  {
  	unsigned int handled = 0, port_no;
edea3ab58   Mark Lord   libata: add new d...
415

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

640fdb504   Jeff Garzik   [libata] pdc_adma...
442
443
444
  			if (!qc->err_mask)
  				ata_qc_complete(qc);
  			else {
9af5c9c97   Tejun Heo   libata-link: intr...
445
  				struct ata_eh_info *ehi = &ap->link.eh_info;
640fdb504   Jeff Garzik   [libata] pdc_adma...
446
447
448
449
450
451
452
453
454
455
456
  				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]...
457
  		}
edea3ab58   Mark Lord   libata: add new d...
458
459
460
  	}
  	return handled;
  }
cca3974e4   Jeff Garzik   libata: Grand ren...
461
  static inline unsigned int adma_intr_mmio(struct ata_host *host)
edea3ab58   Mark Lord   libata: add new d...
462
463
  {
  	unsigned int handled = 0, port_no;
cca3974e4   Jeff Garzik   libata: Grand ren...
464
  	for (port_no = 0; port_no < host->n_ports; ++port_no) {
3e4ec3443   Tejun Heo   libata: kill ATA_...
465
466
467
468
469
470
471
472
473
474
475
476
  		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...
477
  				continue;
3e4ec3443   Tejun Heo   libata: kill ATA_...
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
  			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...
496
  			}
3e4ec3443   Tejun Heo   libata: kill ATA_...
497
  			handled = 1;
edea3ab58   Mark Lord   libata: add new d...
498
499
500
501
  		}
  	}
  	return handled;
  }
7d12e780e   David Howells   IRQ: Maintain reg...
502
  static irqreturn_t adma_intr(int irq, void *dev_instance)
edea3ab58   Mark Lord   libata: add new d...
503
  {
cca3974e4   Jeff Garzik   libata: Grand ren...
504
  	struct ata_host *host = dev_instance;
edea3ab58   Mark Lord   libata: add new d...
505
506
507
508
  	unsigned int handled = 0;
  
  	VPRINTK("ENTER
  ");
cca3974e4   Jeff Garzik   libata: Grand ren...
509
510
511
  	spin_lock(&host->lock);
  	handled  = adma_intr_pkt(host) | adma_intr_mmio(host);
  	spin_unlock(&host->lock);
edea3ab58   Mark Lord   libata: add new d...
512
513
514
515
516
517
  
  	VPRINTK("EXIT
  ");
  
  	return IRQ_RETVAL(handled);
  }
0d5ff5667   Tejun Heo   libata: convert t...
518
  static void adma_ata_setup_port(struct ata_ioports *port, void __iomem *base)
edea3ab58   Mark Lord   libata: add new d...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
  {
  	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...
537
  	struct device *dev = ap->host->dev;
edea3ab58   Mark Lord   libata: add new d...
538
  	struct adma_port_priv *pp;
edea3ab58   Mark Lord   libata: add new d...
539

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

5d728824e   Tejun Heo   libata: convert t...
605
606
607
608
609
610
  	/* 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...
611
  	rc = pcim_enable_device(pdev);
edea3ab58   Mark Lord   libata: add new d...
612
613
  	if (rc)
  		return rc;
24dc5f33e   Tejun Heo   libata: update li...
614
615
  	if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0)
  		return -ENODEV;
edea3ab58   Mark Lord   libata: add new d...
616

0d5ff5667   Tejun Heo   libata: convert t...
617
618
619
  	rc = pcim_iomap_regions(pdev, 1 << ADMA_MMIO_BAR, DRV_NAME);
  	if (rc)
  		return rc;
5d728824e   Tejun Heo   libata: convert t...
620
621
  	host->iomap = pcim_iomap_table(pdev);
  	mmio_base = host->iomap[ADMA_MMIO_BAR];
edea3ab58   Mark Lord   libata: add new d...
622
623
624
  
  	rc = adma_set_dma_masks(pdev, mmio_base);
  	if (rc)
24dc5f33e   Tejun Heo   libata: update li...
625
  		return rc;
edea3ab58   Mark Lord   libata: add new d...
626

cbcdd8759   Tejun Heo   libata: implement...
627
628
629
630
631
632
633
634
635
636
  	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...
637
638
  
  	/* initialize adapter */
5d728824e   Tejun Heo   libata: convert t...
639
  	adma_host_init(host, board_idx);
edea3ab58   Mark Lord   libata: add new d...
640

5d728824e   Tejun Heo   libata: convert t...
641
642
643
  	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...
644
645
646
647
  }
  
  static int __init adma_ata_init(void)
  {
b7887196e   Pavel Roskin   [PATCH] libata: r...
648
  	return pci_register_driver(&adma_ata_pci_driver);
edea3ab58   Mark Lord   libata: add new d...
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
  }
  
  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);