1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#ifndef	_SYS_FDC_H
27#define	_SYS_FDC_H
28
29#ifdef	__cplusplus
30extern "C" {
31#endif
32
33#ifndef	OTYPCNT
34#define	OTYPCNT	5
35#endif
36
37typedef struct xlate_tbl {
38	int	value;
39	uchar_t	code;
40} xlate_tbl_t;
41
42/*
43 * the floppy disk minor device number is interpreted as follows:
44 *
45 *	 7 6 5 4 3 2 1 0
46 * 	+---------+-----+
47 * 	|  drive  | part|
48 * 	+---------+-----+
49 * where:
50 *		drive = instance
51 *		part = partition
52 */
53/*
54 * Macros for partition/drive from floppy device number,
55 * plus other manifest defines....
56 */
57
58#define	PARTITION(x)	(getminor(x) & 7)
59#define	DRIVE(x)	(getminor(x) >> 3)
60#define	FDUNIT(x)	((x) & 3)	/* unit on controller */
61#define	FDCTLR(x)	((x) >> 2)	/* controller instance */
62#define	NFDUN	4
63
64
65/*
66 * Floppy drive / diskette type numbers.
67 */
68#define	FMT_5H	  0
69#define	FMT_5Q	  1
70#define	FMT_5D9	  2
71#define	FMT_5D8	  3
72#define	FMT_5D4	  4
73#define	FMT_5D16  5
74#define	FMT_3E	  6
75#define	FMT_3H	  7
76#define	FMT_3I	  8
77#define	FMT_3M	  9
78#define	FMT_3D	  10
79#define	FMT_AUTO  11
80#define	FMT_MAX	  11
81#define	FMT_UNKWN 11
82
83
84/*
85 * Mini- and Micro- Diskettes Attributes Structure
86 */
87struct fdattr {
88	ushort_t fda_rotatespd;		/* rotational speed */
89	ushort_t fda_intrlv;		/* interleave factor */
90
91	uchar_t fda_gapl;		/* gap 3 length */
92	uchar_t fda_gapf;		/* gap 3 length for format */
93};
94
95/*
96 * Miscellaneous
97 */
98#define	FDWRITE	0			/* for fdrw() flag */
99#define	FDREAD	1			/* for fdrw() flag */
100#define	FDRDONE	86			/*  . read with no retries */
101
102/*
103 * Per floppy-drive / diskette state structure
104 */
105
106struct fdisk {
107	struct fcu_obj	*d_obj;
108	int		d_media;	/* drive media capacities */
109	struct kstat 	*d_iostat;	/* pointer to iostat statistics */
110	int		d_bpsshf;	/* shift count for bytes to sector */
111
112	ksema_t		d_ocsem;	/* sem for serializing opens/closes */
113
114	struct buf	*d_actf;	/* head of wait list */
115	struct buf	*d_actl;	/* tail of wait list */
116	struct buf	*d_current;	/* currently active buf */
117	struct partition d_part[NDKMAP];	/* partitions descriptions */
118
119	/*
120	 * Regular open type flags.
121	 * Open types BLK, MNT, CHR, SWP assumed to be values 0-3.
122	 */
123	ulong_t	d_regopen[OTYPCNT - 1];
124	ulong_t	d_lyropen[NDKMAP];	/* Layered open counters */
125
126	/*
127	 * Exclusive open flags (per partition).
128	 *
129	 * The rules are that in order to open a partition exclusively,
130	 * the partition must be completely closed already. Once any
131	 * partition of the device is opened exclusively, no other open
132	 * on that partition may succeed until the partition is closed.
133	 */
134	ulong_t		d_exclmask;	/* set to indicate exclusive open */
135
136	/*
137	 * Current drive characteristics type.
138	 * If -1, then it was set via an ioctl.  Note that a close
139	 * and then an open loses the ioctl set characteristics.
140	 */
141	signed char	d_curfdtype;
142	uchar_t		d_deffdtype;
143
144	uchar_t		d_bsec;		/* encoded bytes_per_sector */
145	uchar_t		d_drate;	/* encoded data_rate */
146	uchar_t		d_motor;	/* motor-on bit */
147
148	uchar_t		d_hutsrt;	/* encoded head unload & step_rate */
149	uchar_t		d_hlt;		/* encoded head load time */
150	uchar_t		d_dtl;		/* dtl code */
151
152	int	d_media_timeout;	/* media detection timeout */
153	timeout_id_t	d_media_timeout_id; /* media detection timeout id */
154	enum dkio_state d_media_state;	/* up-to-date media state */
155	int		d_ejected;
156	kcondvar_t	d_statecv;	/* condition var for media state */
157
158	ulong_t		d_vtoc_bootinfo[3];	/* from label */
159	ulong_t		d_vtoc_version;
160	time_t		d_vtoc_timestamp[NDKMAP];
161	char		d_vtoc_volume[LEN_DKL_VVOL];
162	char		d_vtoc_asciilabel[LEN_DKL_ASCII];
163};
164
165
166/* a place to keep some statistics on what's going on */
167struct fdstat {
168	/* first operations */
169	int rd;		/* count reads */
170	int wr;		/* count writes */
171	int recal;	/* count recalibrates */
172	int form;	/* count format_tracks */
173	int other;	/* count other ops */
174
175	/* then errors */
176	int reset;	/* count resets */
177	int to;		/* count timeouts */
178	int run;	/* count overrun/underrun */
179	int de;		/* count data errors */
180	int bfmt;	/* count bad format errors */
181};
182
183/*
184 * floppy disk command and status block.
185 *
186 * Needed to execute a command. Since the floppy chip is
187 * single threaded with respect to having only one drive
188 * active at a time, this block of information is only
189 * valid for the length of a command and gets rewritten
190 * for each command.
191 */
192
193enum fxstate {
194	FXS_START,
195	FXS_MTRON,
196	FXS_RCAL,
197	FXS_DKCHGX,
198	FXS_RESTART,
199	FXS_RESEEK,
200	FXS_SEEK,
201	FXS_HDST,
202	FXS_RDID,
203	FXS_DOIT,
204	FXS_DOWT,
205	FXS_KILL,
206	FXS_RESET,
207	FXS_END
208};
209
210enum fmtrstate {
211	FMS_OFF,
212	FMS_START,
213	FMS_KILLST,
214	FMS_ON,
215	FMS_DELAY,
216	FMS_IDLE
217};
218
219enum fmtrinput {
220	FMI_TIMER,
221	FMI_STARTCMD,
222	FMI_RSTARTCMD,
223	FMI_DELAYCMD,
224	FMI_IDLECMD
225};
226
227struct fdcsb {
228	struct buf *csb_bufp;	/* associated buf */
229	ddi_dma_handle_t csb_dmahandle;
230	int csb_handle_bound;		/* DMA handle has been bound */
231	uint_t csb_dmacookiecnt;	/* number of DMA cookies */
232	uint_t csb_dmacurrcookie;	/* current cookie number */
233	uint_t csb_dmawincnt;		/* number of DMA windows */
234	uint_t csb_dmacurrwin;		/* current DMA window */
235	ddi_dma_cookie_t csb_dmacookie;
236	enum fxstate csb_xstate;	/* Current execution state */
237	enum fxstate csb_oldxs;	/* old execution state */
238	uchar_t	csb_npcyl;	/* new physical cylinder number */
239	uchar_t	csb_drive;	/* floppy unit number */
240	uchar_t	csb_ncmds;	/* how many command bytes to send */
241	uchar_t	csb_nrslts;	/* number of result bytes gotten */
242	uchar_t	csb_opflags;	/* opflags, see below */
243	uchar_t	csb_timer;	/* op timer, in 0.1 sec */
244	uchar_t	csb_maxretry;	/* maximum retries this operation */
245	uchar_t	csb_retrys;	/* how may retrys done so far */
246	uchar_t	csb_ourtrys;	/* how may over/underrun retrys done so far */
247	uchar_t	csb_status;	/* status returned from hwintr */
248	uchar_t	csb_cmdstat;	/* if 0 then success, else failure */
249	uchar_t	csb_cmd[10];	/* command to send to chip */
250	uchar_t	csb_rslt[10];	/* results from chip */
251};
252
253/*
254 * defines for csb_opflags
255 */
256#define	CSB_OFINRPT	0x01		/* generates an interrupt */
257#define	CSB_OFDMARD	0x02		/* uses DMA for reading */
258#define	CSB_OFDMAWT	0x04		/* uses DMA for writing */
259#define	CSB_OFRESLT	0x08		/* generates results */
260#define	CSB_OFRAWIOCTL	0x10		/* raw i/o control */
261
262#define	CSB_CMDTO   0x01
263#define	CSB_CMDDMA  0x03
264#define	CSB_CMDNGNR 0x07
265
266
267/*
268 * 82077AA Controller modes
269 */
270enum fdcmode077 {
271	FDCMODE_AT,
272	FDCMODE_PS2,	/* not supported */
273	FDCMODE_30
274};
275
276/*
277 * Per controller data
278 */
279
280struct fdcntlr {
281	kmutex_t	c_lock;		/* controller mutex */
282	kmutex_t	c_dorlock;	/* digital_output_register mutex */
283	kcondvar_t	c_iocv;		/* condition var for I/O done */
284	ksema_t		c_selsem;	/* sem for select unit */
285	boolean_t	c_suspended;	/* if DDI_SUSPENDed */
286
287	dev_info_t	*c_dip;
288	int		c_number;	/* logical controller number */
289	int		c_regbase;	/* base i/o address */
290	int		c_dmachan;	/* DMA channel number */
291	int		c_intprio;	/* interrupt priority */
292	int		c_intvec;	/* interrupt vector num */
293	int		c_chip;
294	enum fdcmode077	c_mode;		/* 82077 controller mode */
295
296	ulong_t		c_flags;	/* state information */
297	struct kstat	*c_intrstat;	/* interrupt stats pointer */
298	struct	fdstat	fdstats;	/* statistics */
299
300	ddi_iblock_cookie_t c_iblock;	/* returned from ddi_add_intr */
301	ddi_idevice_cookie_t c_idevice;	/* returned from ddi_add_intr */
302
303	int		c_curunit;	/* current/last selected unit */
304	timeout_id_t	c_timeid;	/* watchdog timer id */
305
306	struct	fcu_obj	*c_unit[NFDUN];	/* slave on controller */
307	timeout_id_t	c_motort[NFDUN]; /* motor timer id */
308	enum fmtrstate	c_mtrstate[NFDUN];
309	int		c_curpcyl[NFDUN]; /* current physical cylinder */
310	signed char	c_sekdir[NFDUN]; /* direction of last seek */
311
312	struct	fdcsb	c_csb;		/* current csb */
313
314	/*
315	 * floppy controller register values
316	 */
317	uchar_t		c_digout;
318	uchar_t		c_drate;	/* only 82072 and 82077AA controllers */
319	uchar_t		c_config;	/* DSR on PC/AT with 8272A */
320	uchar_t		c_mstat;
321	uchar_t		c_data;
322	uchar_t		c_digin;
323
324	uchar_t		c_bsec;		/* encoded bytes_per_sector */
325	uchar_t		c_hutsrt;	/* encoded head unload & step_rate */
326	uchar_t		c_hlt;		/* encoded head load time */
327};
328
329/*
330 * Controller flags
331 */
332#define	FCFLG_BUSY	0x01	/* operation in progress */
333#define	FCFLG_WANT	0x02	/* csb structure wanted */
334#define	FCFLG_WAITMR	0x10	/* waiting for motor to start I/O */
335#define	FCFLG_WAITING	0x20	/* waiting on I/O completion */
336#define	FCFLG_TIMEOUT	0x80	/* the current operation just timed out */
337#define	FCFLG_DSOUT	0x100	/* DENSEL ouput is in use for speed ctl */
338#define	FCFLG_3DMODE	0x800	/* ctlr is 3D Mode capable */
339
340
341/*
342 * FDC operations
343 */
344
345struct fcobjops {
346	int	(*fco_abort)();		/* controller abort */
347	int	(*fco_dkinfo)();	/* get disk controller info */
348
349	int	(*fco_select)();	/* select / deselect unit */
350	int	(*fco_getchng)();	/* get media change */
351	int	(*fco_resetchng)();	/* reset media change */
352	int	(*fco_rcseek)();	/* recal / seek */
353	int	(*fco_rwbuf)();		/* read /write request */
354	int	(*fco_rw)();		/* read /write sector */
355	int	(*fco_format)();	/* format track */
356	int	(*fco_rwioctl)();	/* raw ioctl */
357};
358
359/*
360 * FDC unit object
361 */
362
363struct fcu_obj {
364	ulong_t		fj_flags;	/* state information */
365	kmutex_t 	fj_lock;	/* unit mutex */
366	caddr_t		fj_data;
367	struct fd_drive *fj_drive;	/* pointer to drive characteristics */
368	struct fd_char	*fj_chars;	/* ptr to diskette characteristics */
369	struct fdattr	*fj_attr;	/* additional diskette attributes */
370	dev_info_t	*fj_dip;
371	ushort_t	fj_rotspd;	/* rotational speed */
372	ulong_t		fj_unit;
373	struct fcobjops *fj_ops;
374	struct fdcntlr	*fj_fdc;
375	ddi_iblock_cookie_t *fj_iblock;
376};
377
378/* unit flags (state info) */
379#define	FUNIT_DRVATCH		0x001	/* this is drive present */
380#define	FUNIT_WPROT		0x004	/* diskette is read only */
381#define	FUNIT_CHAROK		0x010	/* characteristics are known */
382#define	FUNIT_LABELOK		0x020	/* label was read from disk */
383#define	FUNIT_UNLABELED		0x040	/* no label using default */
384#define	FUNIT_CHANGED		0x100	/* diskette was changed after open */
385#define	FUNIT_CHGDET		0x200	/* diskette removal was detected */
386#define	FUNIT_3DMODE		0x4000	/* unit is in fast speed mode */
387#define	FUNIT_BUSY		0x8000	/* unit is busy */
388
389#ifdef _VPIX
390#define	DRV_NONE	0x00
391#define	DRV_DBL		0x01
392#define	DRV_QUAD	0x02
393#define	DRV_720		0x04	/* LOW_35 gets changed to this for or'ing */
394#define	DRV_144		0x08	/* HI35 gets changed to this for or'ing */
395
396/* ioctl numbers used by VPIX */
397#define	FIOC		('F'<<8)
398#define	F_DTYP		(FIOC|60)	/* returns fd_drvtype */
399#define	F_FCR		(FIOC|61)	/* output to Floppy Control Register */
400#define	F_DOR		(FIOC|62)	/* output to Digital Output Register */
401#define	F_RAW		(FIOC|63)	/* general raw controller interface */
402#endif
403
404#ifdef	__cplusplus
405}
406#endif
407
408#endif	/* !_SYS_FDC_H */
409