summaryrefslogtreecommitdiff
path: root/drivers/scsi/arm/fas216.h
blob: 08113277a2a973d40e473072b9b7067cd61d47c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
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
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
403
404
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 *  linux/drivers/acorn/scsi/fas216.h
 *
 *  Copyright (C) 1997-2000 Russell King
 *
 *  FAS216 generic driver
 */
#ifndef FAS216_H
#define FAS216_H

#include <scsi/scsi_eh.h>

#include "queue.h"
#include "msgqueue.h"

/* FAS register definitions */

/* transfer count low */
#define REG_CTCL		(0)
#define REG_STCL		(0)

/* transfer count medium */
#define REG_CTCM		(1)
#define REG_STCM		(1)

/* fifo data */
#define REG_FF			(2)

/* command */
#define REG_CMD			(3)
#define CMD_NOP			0x00
#define CMD_FLUSHFIFO		0x01
#define CMD_RESETCHIP		0x02
#define CMD_RESETSCSI		0x03

#define CMD_TRANSFERINFO	0x10
#define CMD_INITCMDCOMPLETE	0x11
#define CMD_MSGACCEPTED		0x12
#define CMD_PADBYTES		0x18
#define CMD_SETATN		0x1a
#define CMD_RSETATN		0x1b

#define CMD_SELECTWOATN		0x41
#define CMD_SELECTATN		0x42
#define CMD_SELECTATNSTOP	0x43
#define CMD_ENABLESEL		0x44
#define CMD_DISABLESEL		0x45
#define CMD_SELECTATN3		0x46
#define CMD_RESEL3		0x47

#define CMD_WITHDMA		0x80

/* status register (read) */
#define REG_STAT		(4)
#define STAT_IO			(1 << 0)			/* IO phase		*/
#define STAT_CD			(1 << 1)			/* CD phase		*/
#define STAT_MSG		(1 << 2)			/* MSG phase		*/
#define STAT_TRANSFERDONE	(1 << 3)			/* Transfer completed	*/
#define STAT_TRANSFERCNTZ	(1 << 4)			/* Transfer counter is zero */
#define STAT_PARITYERROR	(1 << 5)			/* Parity error		*/
#define STAT_REALBAD		(1 << 6)			/* Something bad	*/
#define STAT_INT		(1 << 7)			/* Interrupt		*/

#define STAT_BUSMASK		(STAT_MSG|STAT_CD|STAT_IO)
#define STAT_DATAOUT		(0)				/* Data out		*/
#define STAT_DATAIN		(STAT_IO)			/* Data in		*/
#define STAT_COMMAND		(STAT_CD)			/* Command out		*/
#define STAT_STATUS		(STAT_CD|STAT_IO)		/* Status In		*/
#define STAT_MESGOUT		(STAT_MSG|STAT_CD)		/* Message out		*/
#define STAT_MESGIN		(STAT_MSG|STAT_CD|STAT_IO)	/* Message In		*/

/* bus ID for select / reselect */
#define REG_SDID		(4)
#define BUSID(target)		((target) & 7)

/* Interrupt status register (read) */
#define REG_INST		(5)
#define INST_SELWOATN		(1 << 0)			/* Select w/o ATN	*/
#define INST_SELATN		(1 << 1)			/* Select w/ATN		*/
#define INST_RESELECTED		(1 << 2)			/* Reselected		*/
#define INST_FUNCDONE		(1 << 3)			/* Function done	*/
#define INST_BUSSERVICE		(1 << 4)			/* Bus service		*/
#define INST_DISCONNECT		(1 << 5)			/* Disconnect		*/
#define INST_ILLEGALCMD		(1 << 6)			/* Illegal command	*/
#define INST_BUSRESET		(1 << 7)			/* SCSI Bus reset	*/

/* Timeout register (write) */
#define REG_STIM		(5)

/* Sequence step register (read) */
#define REG_IS			(6)
#define IS_BITS			0x07
#define IS_SELARB		0x00				/* Select & Arb ok	*/
#define IS_MSGBYTESENT		0x01				/* One byte message sent*/
#define IS_NOTCOMMAND		0x02				/* Not in command state	*/
#define IS_EARLYPHASE		0x03				/* Early phase change	*/
#define IS_COMPLETE		0x04				/* Command ok		*/
#define IS_SOF			0x08				/* Sync off flag	*/

/* Transfer period step (write) */
#define REG_STP			(6)

/* Synchronous Offset (write) */
#define REG_SOF			(7)

/* Fifo state register (read) */
#define REG_CFIS		(7)
#define CFIS_CF			0x1f				/* Num bytes in FIFO	*/
#define CFIS_IS			0xe0				/* Step			*/

/* config register 1 */
#define REG_CNTL1		(8)
#define CNTL1_CID		(7 << 0)			/* Chip ID			*/
#define CNTL1_STE		(1 << 3)			/* Self test enable		*/
#define CNTL1_PERE		(1 << 4)			/* Parity enable reporting en.	*/
#define CNTL1_PTE		(1 << 5)			/* Parity test enable		*/
#define CNTL1_DISR		(1 << 6)			/* Disable Irq on SCSI reset	*/
#define CNTL1_ETM		(1 << 7)			/* Extended Timing Mode		*/

/* Clock conversion factor (read) */
#define REG_CLKF		(9)
#define CLKF_F37MHZ		0x00				/* 35.01 - 40 MHz		*/
#define CLKF_F10MHZ		0x02				/* 10 MHz			*/
#define CLKF_F12MHZ		0x03				/* 10.01 - 15 MHz		*/
#define CLKF_F17MHZ		0x04				/* 15.01 - 20 MHz		*/
#define CLKF_F22MHZ		0x05				/* 20.01 - 25 MHz		*/
#define CLKF_F27MHZ		0x06				/* 25.01 - 30 MHz		*/
#define CLKF_F32MHZ		0x07				/* 30.01 - 35 MHz		*/

/* Chip test register (write) */
#define REG_FTM			(10)
#define TEST_FTM		0x01				/* Force target mode		*/
#define TEST_FIM		0x02				/* Force initiator mode		*/
#define TEST_FHI		0x04				/* Force high impedance mode	*/

/* Configuration register 2 (read/write) */
#define REG_CNTL2		(11)
#define CNTL2_PGDP		(1 << 0)			/* Pass Th/Generate Data Parity	*/
#define CNTL2_PGRP		(1 << 1)			/* Pass Th/Generate Reg Parity	*/
#define CNTL2_ACDPE		(1 << 2)			/* Abort on Cmd/Data Parity Err	*/
#define CNTL2_S2FE		(1 << 3)			/* SCSI2 Features Enable	*/
#define CNTL2_TSDR		(1 << 4)			/* Tristate DREQ		*/
#define CNTL2_SBO		(1 << 5)			/* Select Byte Order		*/
#define CNTL2_ENF		(1 << 6)			/* Enable features		*/
#define CNTL2_DAE		(1 << 7)			/* Data Alignment Enable	*/

/* Configuration register 3 (read/write) */
#define REG_CNTL3		(12)
#define CNTL3_BS8		(1 << 0)			/* Burst size 8			*/
#define CNTL3_MDM		(1 << 1)			/* Modify DMA mode		*/
#define CNTL3_LBTM		(1 << 2)			/* Last Byte Transfer mode	*/
#define CNTL3_FASTCLK		(1 << 3)			/* Fast SCSI clocking		*/
#define CNTL3_FASTSCSI		(1 << 4)			/* Fast SCSI			*/
#define CNTL3_G2CB		(1 << 5)			/* Group2 SCSI support		*/
#define CNTL3_QTAG		(1 << 6)			/* Enable 3 byte msgs		*/
#define CNTL3_ADIDCHK		(1 << 7)			/* Additional ID check		*/

/* High transfer count (read/write) */
#define REG_CTCH		(14)
#define REG_STCH		(14)

/* ID register (read only) */
#define REG_ID			(14)

/* Data alignment */
#define REG_DAL			(15)

typedef enum {
	PHASE_IDLE,					/* we're not planning on doing anything	*/
	PHASE_SELECTION,				/* selecting a device			*/
	PHASE_SELSTEPS,					/* selection with command steps		*/
	PHASE_COMMAND,					/* command sent				*/
	PHASE_MESSAGESENT,				/* selected, and we're sending cmd	*/
	PHASE_DATAOUT,					/* data out to device			*/
	PHASE_DATAIN,					/* data in from device			*/
	PHASE_MSGIN,					/* message in from device		*/
	PHASE_MSGIN_DISCONNECT,				/* disconnecting from bus		*/
	PHASE_MSGOUT,					/* after message out phase		*/
	PHASE_MSGOUT_EXPECT,				/* expecting message out		*/
	PHASE_STATUS,					/* status from device			*/
	PHASE_DONE					/* Command complete			*/
} phase_t;

typedef enum {
	DMA_OUT,					/* DMA from memory to chip		*/
	DMA_IN						/* DMA from chip to memory		*/
} fasdmadir_t;

typedef enum {
	fasdma_none,					/* No dma				*/
	fasdma_pio,					/* PIO mode				*/
	fasdma_pseudo,					/* Pseudo DMA				*/
	fasdma_real_block,				/* Real DMA, on block by block basis	*/
	fasdma_real_all					/* Real DMA, on request by request	*/
} fasdmatype_t;

typedef enum {
	neg_wait,					/* Negotiate with device		*/
	neg_inprogress,					/* Negotiation sent			*/
	neg_complete,					/* Negotiation complete			*/
	neg_targcomplete,				/* Target completed negotiation		*/
	neg_invalid					/* Negotiation not supported		*/
} neg_t;

#define MAGIC	0x441296bdUL
#define NR_MSGS	8

#define FASCAP_DMA		(1 << 0)
#define FASCAP_PSEUDODMA	(1 << 1)

typedef struct {
	unsigned long		magic_start;
	spinlock_t		host_lock;
	struct Scsi_Host	*host;			/* host					*/
	struct scsi_cmnd	*SCpnt;			/* currently processing command		*/
	struct scsi_cmnd	*origSCpnt;		/* original connecting command		*/
	struct scsi_cmnd	*reqSCpnt;		/* request sense command		*/
	struct scsi_cmnd	*rstSCpnt;		/* reset command			*/
	struct scsi_cmnd	*pending_SCpnt[8];	/* per-device pending commands		*/
	int			next_pending;		/* next pending device			*/

	/*
	 * Error recovery
	 */
	wait_queue_head_t	eh_wait;
	struct timer_list	eh_timer;
	unsigned int		rst_dev_status;
	unsigned int		rst_bus_status;

	/* driver information */
	struct {
		phase_t		phase;			/* current phase			*/
		void __iomem	*io_base;		/* iomem base of FAS216			*/
		unsigned int	io_shift;		/* shift to adjust reg offsets by	*/
		unsigned char	cfg[4];			/* configuration registers		*/
		const char	*type;			/* chip type				*/
		unsigned int	irq;			/* interrupt				*/
		int		dma;			/* dma channel				*/

		struct scsi_pointer	SCp;			/* current commands data pointer	*/

		MsgQueue_t	msgs;			/* message queue for connected device	*/

		unsigned int	async_stp;		/* Async transfer STP value		*/
		unsigned char	msgin_fifo;		/* bytes in fifo at time of message in	*/
		unsigned char	message[256];		/* last message received from device	*/

		unsigned char	disconnectable:1;	/* this command can be disconnected	*/
		unsigned char	aborting:1;		/* aborting command			*/
	} scsi;

	/* statistics information */
	struct {
		unsigned int	queues;
		unsigned int	removes;
		unsigned int	fins;
		unsigned int	reads;
		unsigned int	writes;
		unsigned int	miscs;
		unsigned int	disconnects;
		unsigned int	aborts;
		unsigned int	bus_resets;
		unsigned int	host_resets;
	} stats;

	/* configuration information */
	struct {
		unsigned char	clockrate;		/* clock rate of FAS device (MHz)	*/
		unsigned char	select_timeout;		/* timeout (R5)				*/
		unsigned char	sync_max_depth;		/* Synchronous xfer max fifo depth	*/
		unsigned char	wide_max_size;		/* Maximum wide transfer size		*/
		unsigned char	cntl3;			/* Control Reg 3			*/
		unsigned int	asyncperiod;		/* Async transfer period (ns)		*/
		unsigned int	capabilities;		/* driver capabilities			*/
		unsigned int	disconnect_ok:1;	/* Disconnects allowed?			*/
	} ifcfg;

	/* queue handling */
	struct {
	    	Queue_t		issue;			/* issue queue				*/
    		Queue_t		disconnected;		/* disconnected command queue		*/
	} queues;

	/* per-device info */
	struct fas216_device {
		unsigned char	disconnect_ok:1;	/* device can disconnect		*/
		unsigned char	parity_enabled:1;	/* parity checking enabled		*/
		unsigned char	parity_check:1;		/* need to check parity checking	*/
		unsigned char	period;			/* sync xfer period in (*4ns)		*/
		unsigned char	stp;			/* synchronous transfer period		*/
		unsigned char	sof;			/* synchronous offset register		*/
		unsigned char	wide_xfer;		/* currently negociated wide transfer	*/
		neg_t		sync_state;		/* synchronous transfer mode		*/
		neg_t		wide_state;		/* wide transfer mode			*/
	} device[8];
	unsigned long	busyluns[64/sizeof(unsigned long)];/* array of bits indicating LUNs busy	*/

	/* dma */
	struct {
		fasdmatype_t	transfer_type;		/* current type of DMA transfer		*/
		fasdmatype_t	(*setup) (struct Scsi_Host *host, struct scsi_pointer *SCp, fasdmadir_t direction, fasdmatype_t min_dma);
		void		(*pseudo)(struct Scsi_Host *host, struct scsi_pointer *SCp, fasdmadir_t direction, int transfer);
		void		(*stop)  (struct Scsi_Host *host, struct scsi_pointer *SCp);
	} dma;

	/* miscellaneous */
	int			internal_done;		/* flag to indicate request done */
	struct scsi_eh_save	ses;		/* holds request sense restore info */
	unsigned long		magic_end;
} FAS216_Info;

/* driver-private data per SCSI command. */
struct fas216_cmd_priv {
	/*
	 * @scsi_pointer must be the first member. See also arm_scsi_pointer().
	 */
	struct scsi_pointer scsi_pointer;
	void (*scsi_done)(struct scsi_cmnd *cmd);
};

static inline struct fas216_cmd_priv *fas216_cmd_priv(struct scsi_cmnd *cmd)
{
	return scsi_cmd_priv(cmd);
}

/* Function: int fas216_init (struct Scsi_Host *instance)
 * Purpose : initialise FAS/NCR/AMD SCSI structures.
 * Params  : instance - a driver-specific filled-out structure
 * Returns : 0 on success
 */
extern int fas216_init (struct Scsi_Host *instance);

/* Function: int fas216_add (struct Scsi_Host *instance, struct device *dev)
 * Purpose : initialise FAS/NCR/AMD SCSI ic.
 * Params  : instance - a driver-specific filled-out structure
 * Returns : 0 on success
 */
extern int fas216_add (struct Scsi_Host *instance, struct device *dev);

/* Function: int fas216_queue_command(struct Scsi_Host *h, struct scsi_cmnd *SCpnt)
 * Purpose : queue a command for adapter to process.
 * Params  : h - host adapter
 *	   : SCpnt - Command to queue
 * Returns : 0 - success, else error
 */
extern int fas216_queue_command(struct Scsi_Host *h, struct scsi_cmnd *SCpnt);

/* Function: int fas216_noqueue_command(struct Scsi_Host *h, struct scsi_cmnd *SCpnt)
 * Purpose : queue a command for adapter to process, and process it to completion.
 * Params  : h - host adapter
 *	   : SCpnt - Command to queue
 * Returns : 0 - success, else error
 */
extern int fas216_noqueue_command(struct Scsi_Host *, struct scsi_cmnd *);

/* Function: irqreturn_t fas216_intr (FAS216_Info *info)
 * Purpose : handle interrupts from the interface to progress a command
 * Params  : info - interface to service
 */
extern irqreturn_t fas216_intr (FAS216_Info *info);

extern void fas216_remove (struct Scsi_Host *instance);

/* Function: void fas216_release (struct Scsi_Host *instance)
 * Purpose : release all resources and put everything to bed for FAS/NCR/AMD SCSI ic.
 * Params  : instance - a driver-specific filled-out structure
 * Returns : 0 on success
 */
extern void fas216_release (struct Scsi_Host *instance);

extern void fas216_print_host(FAS216_Info *info, struct seq_file *m);
extern void fas216_print_stats(FAS216_Info *info, struct seq_file *m);
extern void fas216_print_devices(FAS216_Info *info, struct seq_file *m);

/* Function: int fas216_eh_abort(struct scsi_cmnd *SCpnt)
 * Purpose : abort this command
 * Params  : SCpnt - command to abort
 * Returns : FAILED if unable to abort
 */
extern int fas216_eh_abort(struct scsi_cmnd *SCpnt);

/* Function: int fas216_eh_device_reset(struct scsi_cmnd *SCpnt)
 * Purpose : Reset the device associated with this command
 * Params  : SCpnt - command specifing device to reset
 * Returns : FAILED if unable to reset
 */
extern int fas216_eh_device_reset(struct scsi_cmnd *SCpnt);

/* Function: int fas216_eh_bus_reset(struct scsi_cmnd *SCpnt)
 * Purpose : Reset the complete bus associated with this command
 * Params  : SCpnt - command specifing bus to reset
 * Returns : FAILED if unable to reset
 */
extern int fas216_eh_bus_reset(struct scsi_cmnd *SCpnt);

/* Function: int fas216_eh_host_reset(struct scsi_cmnd *SCpnt)
 * Purpose : Reset the host associated with this command
 * Params  : SCpnt - command specifing host to reset
 * Returns : FAILED if unable to reset
 */
extern int fas216_eh_host_reset(struct scsi_cmnd *SCpnt);

#endif /* FAS216_H */