summaryrefslogtreecommitdiff
path: root/sys/dev/ic/gdtvar.h
blob: 3672eda34dda517a63131b4748f2660f4ab14fb0 (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
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
/*	$OpenBSD: gdtvar.h,v 1.7 2002/06/11 03:34:53 niklas Exp $	*/

/*
 * Copyright (c) 1999, 2000 Niklas Hallqvist.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Niklas Hallqvist.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * This driver would not have written if it was not for the hardware donations
 * from both ICP-Vortex and Öko.neT.  I want to thank them for their support.
 */

#define GDT_IOCTL_DUMMY _IOWR('B', 32, struct gdt_dummy)
struct gdt_dummy {
	void *cookie;
	int x;
};

/* XXX Is this pragma necessary?  */
#pragma pack(1)

#define GDT_SCRATCH_SZ 4096

#define GDT_IOCTL_GENERAL _IOWR('B', 33, gdt_ucmd_t)	/* general IOCTL */
typedef struct gdt_ucmd {
	void *cookie;
	u_int16_t io_node;
	u_int16_t service;
	u_int32_t timeout;
	u_int16_t status;
	u_int32_t info;

	u_int32_t BoardNode;			/* board node (always 0) */
	u_int32_t CommandIndex;			/* command number */
	u_int16_t OpCode;			/* the command (READ,..) */
	union {
		struct {
			u_int16_t DeviceNo;	/* number of cache drive */
			u_int32_t BlockNo;	/* block number */
			u_int32_t BlockCnt;	/* block count */
			void	*DestAddr;	/* data */
		} cache;			/* cache service cmd. str. */
		struct {
			u_int16_t param_size;	/* size of p_param buffer */
			u_int32_t subfunc;	/* IOCTL function */
			u_int32_t channel;	/* device */
			void	*p_param;	/* data */
		} ioctl;			/* IOCTL command structure */
		struct {
			u_int16_t reserved;
			u_int32_t direction;	/* data direction */
			u_int32_t mdisc_time;	/* disc. time (0: no timeout)*/
			u_int32_t mcon_time;	/* connect time(0: no to.) */
			void	*sdata;		/* dest. addr. (if s/g: -1) */
			u_int32_t sdlen;	/* data length (bytes) */
			u_int32_t clen;		/* SCSI cmd. length(6,10,12) */
			u_int8_t cmd[12];	/* SCSI command */
			u_int8_t target;	/* target ID */
			u_int8_t lun;		/* LUN */
			u_int8_t bus;		/* SCSI bus number */
			u_int8_t priority;	/* only 0 used */
			u_int32_t sense_len;	/* sense data length */
			void	*sense_data;	/* sense data addr. */
			u_int32_t link_p;	/* linked cmds (not supp.) */
		} raw;				/* raw service cmd. struct. */
	} u;
	u_int8_t data[GDT_SCRATCH_SZ];
	int	complete_flag;
	TAILQ_ENTRY(gdt_ucmd) links;
} gdt_ucmd_t;

#define GDT_IOCTL_DRVERS _IOWR('B', 34, int)	/* get driver version */
typedef struct gdt_drvers {
	void *cookie;
	int vers;
} gdt_drvers_t;

#define GDT_IOCTL_CTRTYPE _IOR('B', 35, gdt_ctrt_t)	/* get ctr. type */
typedef struct gdt_ctrt {
	void *cookie;
	u_int16_t io_node;
	u_int16_t oem_id;
	u_int16_t type;
	u_int32_t info;
	u_int8_t access;
	u_int8_t remote;
	u_int16_t ext_type;
	u_int16_t device_id;
	u_int16_t sub_device_id;
} gdt_ctrt_t;

#define GDT_IOCTL_OSVERS _IOR('B', 36, gdt_osv_t)	/* get OS version */
typedef struct gdt_osv {
	void *cookie;
	u_int8_t oscode;
	u_int8_t version;
	u_int8_t subversion;
	u_int16_t revision;
	char	name[64];
} gdt_osv_t;

#define GDT_IOCTL_CTRCNT _IOR('B', 37, int)	/* get ctr. count */
typedef struct gdt_ctrcnt {
	void *cookie;
	int cnt;
} gdt_ctrcnt_t;

#define GDT_IOCTL_EVENT _IOWR('B', 38, gdt_event_t)	/* get event */

typedef struct {
	u_int16_t size;		/* size of structure */
	union {
		char	stream[16];
		struct {
			u_int16_t ionode;
			u_int16_t service;
			u_int32_t index;
		} driver;
		struct {
			u_int16_t ionode;
			u_int16_t service;
			u_int16_t status;
			u_int32_t info;
			u_int8_t scsi_coord[3];
		} async;
		struct {
			u_int16_t ionode;
			u_int16_t service;
			u_int16_t status;
			u_int32_t info;
			u_int16_t hostdrive;
			u_int8_t scsi_coord[3];
			u_int8_t sense_key;
		} sync;
		struct {
			u_int32_t l1, l2, l3, l4;
		} test;
	} eu;
	u_int32_t severity;
	u_int8_t event_string[256];          
} gdt_evt_data;
#define GDT_ES_ASYNC	1
#define GDT_ES_DRIVER	2
#define GDT_ES_TEST	3
#define GDT_ES_SYNC	4

/* dvrevt structure */
typedef struct {
	u_int32_t first_stamp;
	u_int32_t last_stamp;
	u_int16_t same_count;
	u_int16_t event_source;
	u_int16_t event_idx;
	u_int8_t application;
	u_int8_t reserved;
	gdt_evt_data event_data;
} gdt_evt_str;

typedef struct gdt_event {
	void *cookie;
	int erase;
	int handle;
	gdt_evt_str dvr;
} gdt_event_t;

#define GDT_IOCTL_STATIST _IOR('B', 39, gdt_statist_t) /* get statistics */
typedef struct gdt_statist {
	void *cookie;
	u_int16_t io_count_act;
	u_int16_t io_count_max;
	u_int16_t req_queue_act;
	u_int16_t req_queue_max;
	u_int16_t cmd_index_act;
	u_int16_t cmd_index_max;
	u_int16_t sg_count_act;
	u_int16_t sg_count_max;
} gdt_statist_t;

#pragma pack()

#ifdef _KERNEL

/* Debugging */
#ifdef GDT_DEBUG
#define GDT_DPRINTF(mask, args) if (gdt_debug & (mask)) printf args
#define GDT_D_INTR	0x01
#define GDT_D_MISC	0x02
#define GDT_D_CMD	0x04
#define GDT_D_QUEUE	0x08
#define GDT_D_IO	0x10
extern int gdt_debug;
#else
#define GDT_DPRINTF(mask, args)
#endif

/* Miscellaneous constants */
#define GDT_RETRIES		100000000	/* 100000 * 1us = 100s */
#define GDT_TIMEOUT		100000000	/* 100000 * 1us = 100s */
#define GDT_POLL_TIMEOUT	10000000	/* 10000 * 1us = 10s */
#define GDT_WATCH_TIMEOUT	10000		/* 10000 * 1ms = 10s */

/* Context structure for interrupt services */
struct gdt_intr_ctx {
	u_int32_t info, info2;
	u_int16_t cmd_status, service;
	u_int8_t istatus;
};

/*
 * A command contol block, one for each corresponding command index of the
 * controller.
 */
struct gdt_ccb {
	TAILQ_ENTRY(gdt_ccb) gc_chain;
	struct scsi_xfer *gc_xs;
	struct gdt_ucmd *gc_ucmd;
	bus_dmamap_t gc_dmamap_xfer;
	int gc_timeout;
	u_int32_t gc_info;
	u_int32_t gc_blockno;
	u_int32_t gc_blockcnt;
	u_int16_t gc_status;
	u_int8_t gc_service;
	u_int8_t gc_cmd_index;
	u_int8_t gc_flags;
#define GDT_GCF_CMD_MASK	0x3
#define GDT_GCF_UNUSED		0	
#define GDT_GCF_INTERNAL	1
#define GDT_GCF_SCREEN 		2
#define GDT_GCF_SCSI 		3
#define GDT_GCF_WATCHDOG 	0x4
};

static __inline__ int gdt_ccb_set_cmd(struct gdt_ccb *, int);
static __inline__ int
gdt_ccb_set_cmd(ccb, flag)
	struct gdt_ccb *ccb;
	int flag;
{
	int rv = ccb->gc_flags & GDT_GCF_CMD_MASK;

	ccb->gc_flags &= ~GDT_GCF_CMD_MASK;
	ccb->gc_flags |= flag;
	return (rv);
}

struct gdt_softc {
	struct	device sc_dev;
	void   *sc_ih;
	struct	scsi_link sc_link;	/* Virtual SCSI bus for cache devs */
	struct	scsi_link *sc_raw_link;	/* Raw SCSI busses */

	int	sc_class;		/* Controller class */
#define GDT_ISA		0x01
#define GDT_EISA	0x02
#define GDT_PCI		0x03
#define GDT_PCINEW	0x04
#define GDT_MPR		0x05
#define GDT_CLASS_MASK	0x07
#define GDT_FC		0x10
#define GDT_CLASS(gdt)	((gdt)->sc_class & GDT_CLASS_MASK)

	bus_space_tag_t sc_dpmemt;
	bus_space_handle_t sc_dpmemh;
	bus_addr_t sc_dpmembase;
	bus_dma_tag_t sc_dmat;

	/* XXX These could go into a class-dependent opaque struct instead */
	bus_space_tag_t sc_iot;
	bus_space_handle_t sc_ioh;
	bus_addr_t sc_iobase;

	u_int16_t sc_ic_all_size;

	struct gdt_ccb sc_ccbs[GDT_MAXCMDS];
	TAILQ_HEAD(, gdt_ccb) sc_free_ccb, sc_ccbq;
	TAILQ_HEAD(, gdt_ucmd) sc_ucmdq;
	LIST_HEAD(, scsi_xfer) sc_queue;
	struct scsi_xfer *sc_queuelast;

	u_int16_t sc_cmd_len;
	u_int16_t sc_cmd_off;
	u_int16_t sc_cmd_cnt;
	u_int8_t sc_cmd[GDT_CMD_SZ];

	u_int32_t sc_info;
	u_int32_t sc_info2;
	bus_dma_segment_t sc_scratch_seg;
	caddr_t sc_scratch;
	u_int16_t sc_status;

	u_int8_t sc_bus_cnt;
	u_int8_t sc_bus_id[GDT_MAXBUS];
	u_int8_t sc_more_proc;

	struct {
		u_int8_t hd_present;
		u_int8_t hd_is_logdrv;
		u_int8_t hd_is_arraydrv;
		u_int8_t hd_is_master;
		u_int8_t hd_is_parity;
		u_int8_t hd_is_hotfix;
		u_int8_t hd_master_no;
		u_int8_t hd_lock;
		u_int8_t hd_heads;
		u_int8_t hd_secs;
		u_int16_t hd_devtype;
		u_int32_t hd_size;
		u_int8_t hd_ldr_no;
		u_int8_t hd_rw_attribs;
		u_int32_t hd_start_sec;
	} sc_hdr[GDT_MAX_HDRIVES];

	struct {
		u_int32_t cp_version;
		u_int16_t cp_state;
		u_int16_t cp_strategy;
		u_int16_t cp_write_back;
		u_int16_t cp_block_size;
	} sc_cpar;

	struct {
		u_int32_t bi_ser_no;		/* serial number */
		u_int8_t bi_oem_id[2];		/* u_int8_t OEM ID */
		u_int16_t bi_ep_flags;		/* eprom flags */
		u_int32_t bi_proc_id;		/* processor ID */
		u_int32_t bi_memsize;		/* memory size (bytes) */
		u_int8_t bi_mem_banks;		/* memory banks */
		u_int8_t bi_chan_type;		/* channel type */
		u_int8_t bi_chan_count;		/* channel count */
		u_int8_t bi_rdongle_pres;	/* dongle present */
		u_int32_t bi_epr_fw_ver;	/* (eprom) firmware ver */
		u_int32_t bi_upd_fw_ver;	/* (update) firmware ver */
		u_int32_t bi_upd_revision;	/* update revision */
		char bi_type_string[16];	/* char controller name */
		char bi_raid_string[16];	/* char RAID firmware name */
		u_int8_t bi_update_pres;	/* update present? */
		u_int8_t bi_xor_pres;		/* XOR engine present */
		u_int8_t bi_prom_type;		/* ROM type (eprom/flash) */
		u_int8_t bi_prom_count;		/* number of ROM devices */
		u_int32_t bi_dup_pres;		/* duplexing module pres? */
		u_int32_t bi_chan_pres;		/* # of exp. channels */
		u_int32_t bi_mem_pres;		/* memory expansion inst? */
		u_int8_t bi_ft_bus_system;	/* fault bus supported? */
		u_int8_t bi_subtype_valid;	/* board_subtype valid */
		u_int8_t bi_board_subtype;	/* subtype/hardware level */
		u_int8_t bi_rampar_pres;	/* RAM parity check hw? */
	} sc_binfo;

	struct {
		u_int8_t bf_chaining;	/* chaining supported */
		u_int8_t bf_striping;	/* striping (RAID-0) supported */
		u_int8_t bf_mirroring;	/* mirroring (RAID-1) supported */
		u_int8_t bf_raid;	/* RAID-4/5/10 supported */
	} sc_bfeat;

	u_int16_t sc_raw_feat;
	u_int16_t sc_cache_feat;

	void (*sc_copy_cmd)(struct gdt_softc *, struct gdt_ccb *);
	u_int8_t (*sc_get_status)(struct gdt_softc *);
	void (*sc_intr)(struct gdt_softc *, struct gdt_intr_ctx *);
	void (*sc_release_event)(struct gdt_softc *, struct gdt_ccb *);
	void (*sc_set_sema0)(struct gdt_softc *);
	int (*sc_test_busy)(struct gdt_softc *);
};

/* XXX These have to become spinlocks in case of SMP */
#define GDT_LOCK_GDT(gdt) splbio()
#define GDT_UNLOCK_GDT(gdt, lock) splx(lock)
typedef int gdt_lock_t;

void	gdtminphys(struct buf *);
int	gdt_attach(struct gdt_softc *);
int	gdt_intr(void *);

#ifdef __GNUC__
/* These all require correctly aligned buffers */
static __inline__ void gdt_enc16(u_int8_t *, u_int16_t);
static __inline__ void gdt_enc32(u_int8_t *, u_int32_t);
static __inline__ u_int16_t gdt_dec16(u_int8_t *);
static __inline__ u_int32_t gdt_dec32(u_int8_t *);

static __inline__ void
gdt_enc16(addr, value)
	u_int8_t *addr;
	u_int16_t value;
{
	*(u_int16_t *)addr = htole16(value);
}

static __inline__ void
gdt_enc32(addr, value)
	u_int8_t *addr;
	u_int32_t value;
{
	*(u_int32_t *)addr = htole32(value);
}

static __inline__ u_int16_t
gdt_dec16(addr)
	u_int8_t *addr;
{
	return letoh16(*(u_int16_t *)addr);
}

static __inline__ u_int32_t
gdt_dec32(addr)
	u_int8_t *addr;
{
	return letoh32(*(u_int32_t *)addr);
}
#endif

#if defined(__alpha__)
/* XXX XXX NEED REAL DMA MAPPING SUPPORT XXX XXX */
#undef vtophys
#define	vtophys(va)	alpha_XXX_dmamap((vm_offset_t)(va))
#endif

extern u_int8_t gdt_polling;

#endif