Blame view

drivers/ata/pdc_adma.c 15.4 KB
c82ee6d3b   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
edea3ab58   Mark Lord   libata: add new d...
2
3
4
  /*
   *  pdc_adma.c - Pacific Digital Corporation ADMA
   *
8c3d3d4b1   Tejun Heo   libata: update "M...
5
   *  Maintained by:  Tejun Heo <tj@kernel.org>
edea3ab58   Mark Lord   libata: add new d...
6
7
8
   *
   *  Copyright 2005 Mark Lord
   *
68399bb50   Jeff Garzik   [libata pdc_adma]...
9
   *  libata documentation is available via 'make {ps|pdf}docs',
19285f3c4   Mauro Carvalho Chehab   ata: update refer...
10
   *  as Documentation/driver-api/libata.rst
edea3ab58   Mark Lord   libata: add new d...
11
   *
edea3ab58   Mark Lord   libata: add new d...
12
13
14
15
16
   *  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.
edea3ab58   Mark Lord   libata: add new d...
17
18
19
20
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
21
  #include <linux/gfp.h>
edea3ab58   Mark Lord   libata: add new d...
22
  #include <linux/pci.h>
edea3ab58   Mark Lord   libata: add new d...
23
24
25
  #include <linux/blkdev.h>
  #include <linux/delay.h>
  #include <linux/interrupt.h>
a9524a76f   Jeff Garzik   [libata] use dev_...
26
  #include <linux/device.h>
edea3ab58   Mark Lord   libata: add new d...
27
  #include <scsi/scsi_host.h>
edea3ab58   Mark Lord   libata: add new d...
28
29
30
  #include <linux/libata.h>
  
  #define DRV_NAME	"pdc_adma"
2a3103ce4   Jeff Garzik   [libata] Bump dri...
31
  #define DRV_VERSION	"1.0"
edea3ab58   Mark Lord   libata: add new d...
32
33
  
  /* macro to calculate base address for ATA regs */
5796d1c4c   Jeff Garzik   [libata] Address ...
34
  #define ADMA_ATA_REGS(base, port_no)	((base) + ((port_no) * 0x40))
edea3ab58   Mark Lord   libata: add new d...
35
36
  
  /* macro to calculate base address for ADMA regs */
5796d1c4c   Jeff Garzik   [libata] Address ...
37
  #define ADMA_REGS(base, port_no)	((base) + 0x80 + ((port_no) * 0x20))
0d5ff5667   Tejun Heo   libata: convert t...
38

5d728824e   Tejun Heo   libata: convert t...
39
40
41
  /* 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...
42
43
  
  enum {
0d5ff5667   Tejun Heo   libata: convert t...
44
  	ADMA_MMIO_BAR		= 4,
edea3ab58   Mark Lord   libata: add new d...
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  	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...
69
70
71
72
73
74
75
76
77
  	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...
78
  	cATERR			= (1 << 3),
edea3ab58   Mark Lord   libata: add new d...
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
  	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 ...
112
  static int adma_ata_init_one(struct pci_dev *pdev,
edea3ab58   Mark Lord   libata: add new d...
113
  				const struct pci_device_id *ent);
edea3ab58   Mark Lord   libata: add new d...
114
  static int adma_port_start(struct ata_port *ap);
edea3ab58   Mark Lord   libata: add new d...
115
  static void adma_port_stop(struct ata_port *ap);
95364f367   Jiri Slaby   ata: make qc_prep...
116
  static enum ata_completion_errors adma_qc_prep(struct ata_queued_cmd *qc);
9a3d9eb01   Tejun Heo   [PATCH] libata: r...
117
  static unsigned int adma_qc_issue(struct ata_queued_cmd *qc);
edea3ab58   Mark Lord   libata: add new d...
118
  static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
640fdb504   Jeff Garzik   [libata] pdc_adma...
119
120
  static void adma_freeze(struct ata_port *ap);
  static void adma_thaw(struct ata_port *ap);
a1efdaba2   Tejun Heo   libata: make rese...
121
  static int adma_prereset(struct ata_link *link, unsigned long deadline);
edea3ab58   Mark Lord   libata: add new d...
122

193515d51   Jeff Garzik   [libata] eliminat...
123
  static struct scsi_host_template adma_ata_sht = {
68d1d07b5   Tejun Heo   libata: implement...
124
  	ATA_BASE_SHT(DRV_NAME),
edea3ab58   Mark Lord   libata: add new d...
125
  	.sg_tablesize		= LIBATA_MAX_PRD,
49de0ac82   Jeff Garzik   [libata] pdc_adma...
126
  	.dma_boundary		= ADMA_DMA_BOUNDARY,
edea3ab58   Mark Lord   libata: add new d...
127
  };
029cfd6b7   Tejun Heo   libata: implement...
128
  static struct ata_port_operations adma_ata_ops = {
b0316b15a   Tejun Heo   pdc_adma: inherit...
129
  	.inherits		= &ata_sff_port_ops,
c96f1732e   Alan Cox   [libata] Improve ...
130
  	.lost_interrupt		= ATA_OP_NULL,
029cfd6b7   Tejun Heo   libata: implement...
131
  	.check_atapi_dma	= adma_check_atapi_dma,
edea3ab58   Mark Lord   libata: add new d...
132
133
  	.qc_prep		= adma_qc_prep,
  	.qc_issue		= adma_qc_issue,
029cfd6b7   Tejun Heo   libata: implement...
134

640fdb504   Jeff Garzik   [libata] pdc_adma...
135
136
  	.freeze			= adma_freeze,
  	.thaw			= adma_thaw,
a1efdaba2   Tejun Heo   libata: make rese...
137
  	.prereset		= adma_prereset,
029cfd6b7   Tejun Heo   libata: implement...
138

edea3ab58   Mark Lord   libata: add new d...
139
140
  	.port_start		= adma_port_start,
  	.port_stop		= adma_port_stop,
edea3ab58   Mark Lord   libata: add new d...
141
142
143
144
145
  };
  
  static struct ata_port_info adma_port_info[] = {
  	/* board_1841_idx */
  	{
9cbe056f6   Sergei Shtylyov   libata: remove AT...
146
  		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_POLLING,
14bdef982   Erik Inge Bolsø   [libata] convert ...
147
  		.pio_mask	= ATA_PIO4_ONLY,
bf6263a85   Jeff Garzik   [libata] Use ATA_...
148
  		.udma_mask	= ATA_UDMA4,
edea3ab58   Mark Lord   libata: add new d...
149
150
151
  		.port_ops	= &adma_ata_ops,
  	},
  };
3b7d697df   Jeff Garzik   [libata] constify...
152
  static const struct pci_device_id adma_ata_pci_tbl[] = {
54bb3a94b   Jeff Garzik   [libata] Use new ...
153
  	{ PCI_VDEVICE(PDC, 0x1841), board_1841_idx },
edea3ab58   Mark Lord   libata: add new d...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  
  	{ }	/* 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...
169
  static void adma_reset_engine(struct ata_port *ap)
edea3ab58   Mark Lord   libata: add new d...
170
  {
5d728824e   Tejun Heo   libata: convert t...
171
  	void __iomem *chan = ADMA_PORT_REGS(ap);
edea3ab58   Mark Lord   libata: add new d...
172
173
174
175
176
177
178
179
180
181
  	/* 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...
182
  	void __iomem *chan = ADMA_PORT_REGS(ap);
edea3ab58   Mark Lord   libata: add new d...
183
184
  
  	/* mask/clear ATA interrupts */
0d5ff5667   Tejun Heo   libata: convert t...
185
  	writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
9363c3825   Tejun Heo   libata: rename SF...
186
  	ata_sff_check_status(ap);
edea3ab58   Mark Lord   libata: add new d...
187
188
  
  	/* reset the ADMA engine */
5d728824e   Tejun Heo   libata: convert t...
189
  	adma_reset_engine(ap);
edea3ab58   Mark Lord   libata: add new d...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
  
  	/* 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...
209
  	void __iomem *chan = ADMA_PORT_REGS(ap);
edea3ab58   Mark Lord   libata: add new d...
210
211
212
213
  
  	writew(aPIOMD4, chan + ADMA_CONTROL);
  	readb(chan + ADMA_STATUS);	/* flush */
  }
640fdb504   Jeff Garzik   [libata] pdc_adma...
214
  static void adma_freeze(struct ata_port *ap)
edea3ab58   Mark Lord   libata: add new d...
215
  {
640fdb504   Jeff Garzik   [libata] pdc_adma...
216
217
218
219
  	void __iomem *chan = ADMA_PORT_REGS(ap);
  
  	/* mask/clear ATA interrupts */
  	writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
9363c3825   Tejun Heo   libata: rename SF...
220
  	ata_sff_check_status(ap);
640fdb504   Jeff Garzik   [libata] pdc_adma...
221
222
223
224
225
226
227
  
  	/* 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...
228

640fdb504   Jeff Garzik   [libata] pdc_adma...
229
230
  static void adma_thaw(struct ata_port *ap)
  {
edea3ab58   Mark Lord   libata: add new d...
231
  	adma_reinit_engine(ap);
edea3ab58   Mark Lord   libata: add new d...
232
  }
0260731f0   Tejun Heo   libata-link: link...
233
  static int adma_prereset(struct ata_link *link, unsigned long deadline)
edea3ab58   Mark Lord   libata: add new d...
234
  {
0260731f0   Tejun Heo   libata-link: link...
235
  	struct ata_port *ap = link->ap;
edea3ab58   Mark Lord   libata: add new d...
236
237
238
239
240
  	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...
241

9363c3825   Tejun Heo   libata: rename SF...
242
  	return ata_sff_prereset(link, deadline);
640fdb504   Jeff Garzik   [libata] pdc_adma...
243
  }
edea3ab58   Mark Lord   libata: add new d...
244
245
  static int adma_fill_sg(struct ata_queued_cmd *qc)
  {
972c26bdd   Jeff Garzik   libata: add ata_s...
246
  	struct scatterlist *sg;
edea3ab58   Mark Lord   libata: add new d...
247
248
  	struct ata_port *ap = qc->ap;
  	struct adma_port_priv *pp = ap->private_data;
3be6cbd73   Jeff Garzik   [libata] kill ata...
249
  	u8  *buf = pp->pkt, *last_buf = NULL;
972c26bdd   Jeff Garzik   libata: add ata_s...
250
  	int i = (2 + buf[3]) * 8;
edea3ab58   Mark Lord   libata: add new d...
251
  	u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0);
ff2aeb1eb   Tejun Heo   libata: convert t...
252
  	unsigned int si;
edea3ab58   Mark Lord   libata: add new d...
253

ff2aeb1eb   Tejun Heo   libata: convert t...
254
  	for_each_sg(qc->sg, sg, qc->n_elem, si) {
edea3ab58   Mark Lord   libata: add new d...
255
256
257
258
259
260
261
262
263
264
  		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...
265
  		last_buf = &buf[i];
edea3ab58   Mark Lord   libata: add new d...
266
267
268
269
  		buf[i++] = pFLAGS;
  		buf[i++] = qc->dev->dma_mode & 0xf;
  		buf[i++] = 0;	/* pPKLW */
  		buf[i++] = 0;	/* reserved */
5796d1c4c   Jeff Garzik   [libata] Address ...
270
271
  		*(__le32 *)(buf + i) =
  			(pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4);
edea3ab58   Mark Lord   libata: add new d...
272
  		i += 4;
db7f44d96   Alan Cox   [PATCH] libata: m...
273
274
  		VPRINTK("PRD[%u] = (0x%lX, 0x%X)
  ", i/4,
edea3ab58   Mark Lord   libata: add new d...
275
276
  					(unsigned long)addr, len);
  	}
3be6cbd73   Jeff Garzik   [libata] kill ata...
277
278
279
  
  	if (likely(last_buf))
  		*last_buf |= pEND;
edea3ab58   Mark Lord   libata: add new d...
280
281
  	return i;
  }
95364f367   Jiri Slaby   ata: make qc_prep...
282
  static enum ata_completion_errors adma_qc_prep(struct ata_queued_cmd *qc)
edea3ab58   Mark Lord   libata: add new d...
283
284
285
286
287
288
289
290
291
292
  {
  	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...
293
  	if (qc->tf.protocol != ATA_PROT_DMA)
95364f367   Jiri Slaby   ata: make qc_prep...
294
  		return AC_ERR_OK;
edea3ab58   Mark Lord   libata: add new d...
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
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
  
  	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
95364f367   Jiri Slaby   ata: make qc_prep...
361
  	return AC_ERR_OK;
edea3ab58   Mark Lord   libata: add new d...
362
363
364
365
366
  }
  
  static inline void adma_packet_start(struct ata_queued_cmd *qc)
  {
  	struct ata_port *ap = qc->ap;
5d728824e   Tejun Heo   libata: convert t...
367
  	void __iomem *chan = ADMA_PORT_REGS(ap);
edea3ab58   Mark Lord   libata: add new d...
368
369
370
371
372
  
  	VPRINTK("ENTER, ap %p
  ", ap);
  
  	/* fire up the ADMA engine */
68399bb50   Jeff Garzik   [libata pdc_adma]...
373
  	writew(aPIOMD4 | aGO, chan + ADMA_CONTROL);
edea3ab58   Mark Lord   libata: add new d...
374
  }
9a3d9eb01   Tejun Heo   [PATCH] libata: r...
375
  static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)
edea3ab58   Mark Lord   libata: add new d...
376
377
378
379
380
381
382
383
  {
  	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...
384
  	case ATAPI_PROT_DMA:
edea3ab58   Mark Lord   libata: add new d...
385
386
387
388
389
390
391
392
  		BUG();
  		break;
  
  	default:
  		break;
  	}
  
  	pp->state = adma_state_mmio;
9363c3825   Tejun Heo   libata: rename SF...
393
  	return ata_sff_qc_issue(qc);
edea3ab58   Mark Lord   libata: add new d...
394
  }
cca3974e4   Jeff Garzik   libata: Grand ren...
395
  static inline unsigned int adma_intr_pkt(struct ata_host *host)
edea3ab58   Mark Lord   libata: add new d...
396
397
  {
  	unsigned int handled = 0, port_no;
edea3ab58   Mark Lord   libata: add new d...
398

cca3974e4   Jeff Garzik   libata: Grand ren...
399
400
  	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...
401
402
  		struct adma_port_priv *pp;
  		struct ata_queued_cmd *qc;
5d728824e   Tejun Heo   libata: convert t...
403
  		void __iomem *chan = ADMA_PORT_REGS(ap);
a7dac447b   Jeff Garzik   [libata] change a...
404
  		u8 status = readb(chan + ADMA_STATUS);
edea3ab58   Mark Lord   libata: add new d...
405
406
407
408
409
  
  		if (status == 0)
  			continue;
  		handled = 1;
  		adma_enter_reg_mode(ap);
edea3ab58   Mark Lord   libata: add new d...
410
411
412
  		pp = ap->private_data;
  		if (!pp || pp->state != adma_state_pkt)
  			continue;
9af5c9c97   Tejun Heo   libata-link: intr...
413
  		qc = ata_qc_from_tag(ap, ap->link.active_tag);
94ec1ef1c   Jeff Garzik   [libata pdc_adma]...
414
  		if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
640fdb504   Jeff Garzik   [libata] pdc_adma...
415
416
417
  			if (status & aPERR)
  				qc->err_mask |= AC_ERR_HOST_BUS;
  			else if ((status & (aPSD | aUIRQ)))
a22e2eb07   Albert Lee   [PATCH] libata: m...
418
  				qc->err_mask |= AC_ERR_OTHER;
640fdb504   Jeff Garzik   [libata] pdc_adma...
419
420
421
  
  			if (pp->pkt[0] & cATERR)
  				qc->err_mask |= AC_ERR_DEV;
a21a84a37   Jeff Garzik   [libata pdc_adma]...
422
  			else if (pp->pkt[0] != cDONE)
a22e2eb07   Albert Lee   [PATCH] libata: m...
423
  				qc->err_mask |= AC_ERR_OTHER;
a7dac447b   Jeff Garzik   [libata] change a...
424

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

edea3ab58   Mark Lord   libata: add new d...
523
  	adma_enter_reg_mode(ap);
24dc5f33e   Tejun Heo   libata: update li...
524
  	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
edea3ab58   Mark Lord   libata: add new d...
525
  	if (!pp)
24dc5f33e   Tejun Heo   libata: update li...
526
527
528
  		return -ENOMEM;
  	pp->pkt = dmam_alloc_coherent(dev, ADMA_PKT_BYTES, &pp->pkt_dma,
  				      GFP_KERNEL);
edea3ab58   Mark Lord   libata: add new d...
529
  	if (!pp->pkt)
24dc5f33e   Tejun Heo   libata: update li...
530
  		return -ENOMEM;
edea3ab58   Mark Lord   libata: add new d...
531
532
  	/* paranoia? */
  	if ((pp->pkt_dma & 7) != 0) {
5796d1c4c   Jeff Garzik   [libata] Address ...
533
534
  		printk(KERN_ERR "bad alignment for pp->pkt_dma: %08x
  ",
edea3ab58   Mark Lord   libata: add new d...
535
  						(u32)pp->pkt_dma);
24dc5f33e   Tejun Heo   libata: update li...
536
  		return -ENOMEM;
edea3ab58   Mark Lord   libata: add new d...
537
  	}
edea3ab58   Mark Lord   libata: add new d...
538
539
540
  	ap->private_data = pp;
  	adma_reinit_engine(ap);
  	return 0;
edea3ab58   Mark Lord   libata: add new d...
541
542
543
544
  }
  
  static void adma_port_stop(struct ata_port *ap)
  {
5d728824e   Tejun Heo   libata: convert t...
545
  	adma_reset_engine(ap);
edea3ab58   Mark Lord   libata: add new d...
546
  }
5d728824e   Tejun Heo   libata: convert t...
547
  static void adma_host_init(struct ata_host *host, unsigned int chip_id)
edea3ab58   Mark Lord   libata: add new d...
548
549
  {
  	unsigned int port_no;
edea3ab58   Mark Lord   libata: add new d...
550
551
  
  	/* enable/lock aGO operation */
5d728824e   Tejun Heo   libata: convert t...
552
  	writeb(7, host->iomap[ADMA_MMIO_BAR] + ADMA_MODE_LOCK);
edea3ab58   Mark Lord   libata: add new d...
553
554
555
  
  	/* reset the ADMA logic */
  	for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
5d728824e   Tejun Heo   libata: convert t...
556
  		adma_reset_engine(host->ports[port_no]);
edea3ab58   Mark Lord   libata: add new d...
557
  }
edea3ab58   Mark Lord   libata: add new d...
558
  static int adma_ata_init_one(struct pci_dev *pdev,
0d5ff5667   Tejun Heo   libata: convert t...
559
  			     const struct pci_device_id *ent)
edea3ab58   Mark Lord   libata: add new d...
560
  {
edea3ab58   Mark Lord   libata: add new d...
561
  	unsigned int board_idx = (unsigned int) ent->driver_data;
5d728824e   Tejun Heo   libata: convert t...
562
563
564
  	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...
565
  	int rc, port_no;
06296a1e6   Joe Perches   ata: Add and use ...
566
  	ata_print_version_once(&pdev->dev, DRV_VERSION);
edea3ab58   Mark Lord   libata: add new d...
567

5d728824e   Tejun Heo   libata: convert t...
568
569
570
571
572
573
  	/* 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...
574
  	rc = pcim_enable_device(pdev);
edea3ab58   Mark Lord   libata: add new d...
575
576
  	if (rc)
  		return rc;
24dc5f33e   Tejun Heo   libata: update li...
577
578
  	if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0)
  		return -ENODEV;
edea3ab58   Mark Lord   libata: add new d...
579

0d5ff5667   Tejun Heo   libata: convert t...
580
581
582
  	rc = pcim_iomap_regions(pdev, 1 << ADMA_MMIO_BAR, DRV_NAME);
  	if (rc)
  		return rc;
5d728824e   Tejun Heo   libata: convert t...
583
584
  	host->iomap = pcim_iomap_table(pdev);
  	mmio_base = host->iomap[ADMA_MMIO_BAR];
edea3ab58   Mark Lord   libata: add new d...
585

94c58148a   Christoph Hellwig   pdc_adma: use dma...
586
587
588
589
  	rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
  	if (rc) {
  		dev_err(&pdev->dev, "32-bit DMA enable failed
  ");
24dc5f33e   Tejun Heo   libata: update li...
590
  		return rc;
94c58148a   Christoph Hellwig   pdc_adma: use dma...
591
  	}
edea3ab58   Mark Lord   libata: add new d...
592

cbcdd8759   Tejun Heo   libata: implement...
593
594
595
596
597
598
599
600
601
602
  	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...
603
604
  
  	/* initialize adapter */
5d728824e   Tejun Heo   libata: convert t...
605
  	adma_host_init(host, board_idx);
edea3ab58   Mark Lord   libata: add new d...
606

5d728824e   Tejun Heo   libata: convert t...
607
608
609
  	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...
610
  }
2fc75da0c   Axel Lin   ata: use module_p...
611
  module_pci_driver(adma_ata_pci_driver);
edea3ab58   Mark Lord   libata: add new d...
612
613
614
615
616
617
  
  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);