xref: /netbsd-src/sys/dev/qbus/rf.c (revision 38ad5e0e870b982a8e4c5b0a6172ac412e905fa7)
1*38ad5e0eSandvar /*	$NetBSD: rf.c,v 1.37 2021/08/12 19:53:18 andvar Exp $	*/
2281464ebSragge /*
3281464ebSragge  * Copyright (c) 2002 Jochen Kunz.
4281464ebSragge  * All rights reserved.
5281464ebSragge  *
6281464ebSragge  * Redistribution and use in source and binary forms, with or without
7281464ebSragge  * modification, are permitted provided that the following conditions
8281464ebSragge  * are met:
9281464ebSragge  * 1. Redistributions of source code must retain the above copyright
10281464ebSragge  *    notice, this list of conditions and the following disclaimer.
11281464ebSragge  * 2. Redistributions in binary form must reproduce the above copyright
12281464ebSragge  *    notice, this list of conditions and the following disclaimer in the
13281464ebSragge  *    documentation and/or other materials provided with the distribution.
14281464ebSragge  * 3. The name of Jochen Kunz may not be used to endorse or promote
15281464ebSragge  *    products derived from this software without specific prior
16281464ebSragge  *    written permission.
17281464ebSragge  *
18281464ebSragge  * THIS SOFTWARE IS PROVIDED BY JOCHEN KUNZ
19281464ebSragge  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20281464ebSragge  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21281464ebSragge  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL JOCHEN KUNZ
22281464ebSragge  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23281464ebSragge  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24281464ebSragge  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25281464ebSragge  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26281464ebSragge  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27281464ebSragge  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28281464ebSragge  * POSSIBILITY OF SUCH DAMAGE.
29281464ebSragge  */
30281464ebSragge 
31281464ebSragge /*
32281464ebSragge TODO:
33281464ebSragge - Better LBN bound checking, block padding for SD disks.
349876532dSwiz - Formatting / "Set Density"
356dc8db11Sryoon - Better error handling / detailed error reason reporting.
36281464ebSragge */
37281464ebSragge 
38365cbd94Slukem #include <sys/cdefs.h>
39*38ad5e0eSandvar __KERNEL_RCSID(0, "$NetBSD: rf.c,v 1.37 2021/08/12 19:53:18 andvar Exp $");
40365cbd94Slukem 
41281464ebSragge /* autoconfig stuff */
42281464ebSragge #include <sys/param.h>
43281464ebSragge #include <sys/device.h>
44281464ebSragge #include <sys/conf.h>
45281464ebSragge #include "locators.h"
46281464ebSragge #include "ioconf.h"
47281464ebSragge 
48281464ebSragge /* bus_space / bus_dma */
49a2a38285Sad #include <sys/bus.h>
50281464ebSragge 
51281464ebSragge /* UniBus / QBus specific stuff */
52281464ebSragge #include <dev/qbus/ubavar.h>
53281464ebSragge 
54281464ebSragge /* disk interface */
55281464ebSragge #include <sys/types.h>
56281464ebSragge #include <sys/disklabel.h>
57281464ebSragge #include <sys/disk.h>
58281464ebSragge 
59281464ebSragge /* general system data and functions */
60281464ebSragge #include <sys/systm.h>
61281464ebSragge #include <sys/ioctl.h>
62281464ebSragge #include <sys/ioccom.h>
63281464ebSragge 
64281464ebSragge /* physio / buffer handling */
65281464ebSragge #include <sys/buf.h>
6605f25dccSyamt #include <sys/bufq.h>
67281464ebSragge 
68281464ebSragge /* tsleep / sleep / wakeup */
69281464ebSragge #include <sys/proc.h>
70281464ebSragge /* hz for above */
71281464ebSragge #include <sys/kernel.h>
72281464ebSragge 
73281464ebSragge /* bit definitions for RX211 */
74281464ebSragge #include <dev/qbus/rfreg.h>
75281464ebSragge 
76281464ebSragge 
77281464ebSragge #define	RFS_DENS	0x0001		/* single or double density */
78281464ebSragge #define	RFS_AD		0x0002		/* density auto detect */
79281464ebSragge #define	RFS_NOTINIT	0x0000		/* not initialized */
80281464ebSragge #define	RFS_PROBING	0x0010		/* density detect / verify started */
81281464ebSragge #define	RFS_FBUF	0x0020		/* Fill Buffer */
82281464ebSragge #define	RFS_EBUF	0x0030		/* Empty Buffer */
83281464ebSragge #define	RFS_WSEC	0x0040		/* Write Sector */
84281464ebSragge #define	RFS_RSEC	0x0050		/* Read Sector */
85281464ebSragge #define	RFS_SMD		0x0060		/* Set Media Density */
86281464ebSragge #define	RFS_RSTAT	0x0070		/* Read Status */
87281464ebSragge #define	RFS_WDDS	0x0080		/* Write Deleted Data Sector */
88281464ebSragge #define	RFS_REC		0x0090		/* Read Error Code */
89281464ebSragge #define	RFS_IDLE	0x00a0		/* controller is idle */
90281464ebSragge #define	RFS_CMDS	0x00f0		/* command mask */
91c049e276Sragge #define	RFS_OPEN_A	0x0100		/* partition a open */
92c049e276Sragge #define	RFS_OPEN_B	0x0200		/* partition b open */
93c049e276Sragge #define	RFS_OPEN_C	0x0400		/* partition c open */
94c049e276Sragge #define	RFS_OPEN_MASK	0x0f00		/* mask for open partitions */
95c049e276Sragge #define RFS_OPEN_SHIFT	8		/* to shift 1 to get RFS_OPEN_A */
96281464ebSragge #define	RFS_SETCMD(rf, state)	((rf) = ((rf) & ~RFS_CMDS) | (state))
97281464ebSragge 
98281464ebSragge 
99281464ebSragge 
100281464ebSragge /* autoconfig stuff */
101dfba8166Smatt static int rfc_match(device_t, cfdata_t, void *);
102dfba8166Smatt static void rfc_attach(device_t, device_t, void *);
103dfba8166Smatt static int rf_match(device_t, cfdata_t, void *);
104dfba8166Smatt static void rf_attach(device_t, device_t, void *);
105281464ebSragge static int rf_print(void *, const char *);
106281464ebSragge 
1079876532dSwiz /* device interface functions / interface to disk(9) */
108281464ebSragge dev_type_open(rfopen);
109281464ebSragge dev_type_close(rfclose);
110281464ebSragge dev_type_read(rfread);
111281464ebSragge dev_type_write(rfwrite);
112281464ebSragge dev_type_ioctl(rfioctl);
113281464ebSragge dev_type_strategy(rfstrategy);
114281464ebSragge dev_type_dump(rfdump);
115281464ebSragge dev_type_size(rfsize);
116281464ebSragge 
117281464ebSragge 
118281464ebSragge /* Entries in block and character major device number switch table. */
119281464ebSragge const struct bdevsw rf_bdevsw = {
120a68f9396Sdholland 	.d_open = rfopen,
121a68f9396Sdholland 	.d_close = rfclose,
122a68f9396Sdholland 	.d_strategy = rfstrategy,
123a68f9396Sdholland 	.d_ioctl = rfioctl,
124a68f9396Sdholland 	.d_dump = rfdump,
125a68f9396Sdholland 	.d_psize = rfsize,
1268c70ef39Sdholland 	.d_discard = nodiscard,
127a68f9396Sdholland 	.d_flag = D_DISK
128281464ebSragge };
129281464ebSragge 
130281464ebSragge const struct cdevsw rf_cdevsw = {
131a68f9396Sdholland 	.d_open = rfopen,
132a68f9396Sdholland 	.d_close = rfclose,
133a68f9396Sdholland 	.d_read = rfread,
134a68f9396Sdholland 	.d_write = rfwrite,
135a68f9396Sdholland 	.d_ioctl = rfioctl,
136a68f9396Sdholland 	.d_stop = nostop,
137a68f9396Sdholland 	.d_tty = notty,
138a68f9396Sdholland 	.d_poll = nopoll,
139a68f9396Sdholland 	.d_mmap = nommap,
140a68f9396Sdholland 	.d_kqfilter = nokqfilter,
141f9228f42Sdholland 	.d_discard = nodiscard,
142a68f9396Sdholland 	.d_flag = D_DISK
143281464ebSragge };
144281464ebSragge 
145281464ebSragge 
146281464ebSragge 
147281464ebSragge struct rfc_softc {
148dfba8166Smatt 	device_t sc_dev;		/* common device data */
149dfba8166Smatt 	device_t sc_childs[2];		/* child devices */
150281464ebSragge 	struct evcnt sc_intr_count;	/* Interrupt counter for statistics */
151281464ebSragge 	struct buf *sc_curbuf;		/* buf that is currently in work */
1529876532dSwiz 	bus_space_tag_t sc_iot;		/* bus_space I/O tag */
1539876532dSwiz 	bus_space_handle_t sc_ioh;	/* bus_space I/O handle */
154281464ebSragge 	bus_dma_tag_t sc_dmat;		/* bus_dma DMA tag */
155281464ebSragge 	bus_dmamap_t sc_dmam;		/* bus_dma DMA map */
15653524e44Schristos 	void *sc_bufidx;		/* current position in buffer data */
157281464ebSragge 	int sc_curchild;		/* child whos bufq is in work */
158281464ebSragge 	int sc_bytesleft;		/* bytes left to transfer */
159281464ebSragge 	u_int8_t type;			/* controller type, 1 or 2 */
160281464ebSragge };
161281464ebSragge 
162281464ebSragge 
163281464ebSragge 
164dfba8166Smatt CFATTACH_DECL_NEW(
165281464ebSragge 	rfc,
166281464ebSragge 	sizeof(struct rfc_softc),
167281464ebSragge 	rfc_match,
168281464ebSragge 	rfc_attach,
169281464ebSragge 	NULL,
170281464ebSragge 	NULL
171281464ebSragge );
172281464ebSragge 
173281464ebSragge 
174281464ebSragge 
175281464ebSragge struct rf_softc {
176dfba8166Smatt 	device_t sc_dev;		/* common device data */
177281464ebSragge 	struct disk sc_disk;		/* common disk device data */
178dfba8166Smatt 	struct rfc_softc *sc_rfc;	/* our parent */
179aec75b1cSyamt 	struct bufq_state *sc_bufq;	/* queue of pending transfers */
180281464ebSragge 	int sc_state;			/* state of drive */
181281464ebSragge 	u_int8_t sc_dnum;		/* drive number, 0 or 1 */
182281464ebSragge };
183281464ebSragge 
184281464ebSragge 
185281464ebSragge 
186dfba8166Smatt CFATTACH_DECL_NEW(
187281464ebSragge 	rf,
188281464ebSragge 	sizeof(struct rf_softc),
189281464ebSragge 	rf_match,
190281464ebSragge 	rf_attach,
191281464ebSragge 	NULL,
192281464ebSragge 	NULL
193281464ebSragge );
194281464ebSragge 
195281464ebSragge 
196281464ebSragge 
197281464ebSragge struct rfc_attach_args {
198281464ebSragge 	u_int8_t type;		/* controller type, 1 or 2 */
199281464ebSragge 	u_int8_t dnum;		/* drive number, 0 or 1 */
200281464ebSragge };
201281464ebSragge 
202281464ebSragge 
203281464ebSragge 
204dfba8166Smatt const struct dkdriver rfdkdriver = {
2056f00c789Smlelstv 	.d_strategy = rfstrategy
206281464ebSragge };
207281464ebSragge 
208281464ebSragge 
209281464ebSragge 
210281464ebSragge /* helper functions */
211281464ebSragge int rfc_sendcmd(struct rfc_softc *, int, int, int);
212c049e276Sragge struct rf_softc* get_new_buf( struct rfc_softc *);
213281464ebSragge static void rfc_intr(void *);
214281464ebSragge 
215281464ebSragge 
216281464ebSragge 
217281464ebSragge /*
218281464ebSragge  * Issue a reset command to the controller and look for the bits in
219281464ebSragge  * RX2CS and RX2ES.
220281464ebSragge  * RX2CS_RX02 and / or RX2CS_DD can be set,
221281464ebSragge  * RX2ES has to be set, all other bits must be 0
222281464ebSragge  */
223281464ebSragge int
rfc_match(device_t parent,cfdata_t match,void * aux)224dfba8166Smatt rfc_match(device_t parent, cfdata_t match, void *aux)
225281464ebSragge {
226281464ebSragge 	struct uba_attach_args *ua = aux;
227281464ebSragge 	int i;
228281464ebSragge 
229281464ebSragge 	/* Issue reset command. */
230281464ebSragge 	bus_space_write_2(ua->ua_iot, ua->ua_ioh, RX2CS, RX2CS_INIT);
231281464ebSragge 	/* Wait for the controller to become ready, that is when
232281464ebSragge 	 * RX2CS_DONE, RX2ES_RDY and RX2ES_ID are set. */
233281464ebSragge 	for (i = 0 ; i < 20 ; i++) {
234281464ebSragge 		if ((bus_space_read_2(ua->ua_iot, ua->ua_ioh, RX2CS)
235281464ebSragge 		    & RX2CS_DONE) != 0
236281464ebSragge 		    && (bus_space_read_2(ua->ua_iot, ua->ua_ioh, RX2ES)
237281464ebSragge 		    & (RX2ES_RDY | RX2ES_ID)) != 0)
238281464ebSragge 			break;
239281464ebSragge 		DELAY(100000);	/* wait 100ms */
240281464ebSragge 	}
241281464ebSragge 	/*
242281464ebSragge 	 * Give up if the timeout has elapsed
243281464ebSragge 	 * and the controller is not ready.
244281464ebSragge 	 */
245281464ebSragge 	if (i >= 20)
246281464ebSragge 		return(0);
247281464ebSragge 	/*
248281464ebSragge 	 * Issue a Read Status command with interrupt enabled.
249281464ebSragge 	 * The uba(4) driver wants to catch the interrupt to get the
250281464ebSragge 	 * interrupt vector and level of the device
251281464ebSragge 	 */
252281464ebSragge 	bus_space_write_2(ua->ua_iot, ua->ua_ioh, RX2CS,
253281464ebSragge 	    RX2CS_RSTAT | RX2CS_IE);
254281464ebSragge 	/*
255281464ebSragge 	 * Wait for command to finish, ignore errors and
256281464ebSragge 	 * abort if the controller does not respond within the timeout
257281464ebSragge 	 */
258281464ebSragge 	for (i = 0 ; i < 20 ; i++) {
259281464ebSragge 		if ((bus_space_read_2(ua->ua_iot, ua->ua_ioh, RX2CS)
260281464ebSragge 		    & (RX2CS_DONE | RX2CS_IE)) != 0
261281464ebSragge 		    && (bus_space_read_2(ua->ua_iot, ua->ua_ioh, RX2ES)
262281464ebSragge 		    & RX2ES_RDY) != 0 )
263281464ebSragge 			return(1);
264281464ebSragge 		DELAY(100000);	/* wait 100ms */
265281464ebSragge 	}
266281464ebSragge 	return(0);
267281464ebSragge }
268281464ebSragge 
269281464ebSragge 
270281464ebSragge 
271281464ebSragge /* #define RX02_PROBE 1 */
272281464ebSragge #ifdef RX02_PROBE
273281464ebSragge /*
274281464ebSragge  * Probe the density of an inserted floppy disk.
275281464ebSragge  * This is done by reading a sector from disk.
276281464ebSragge  * Return -1 on error, 0 on SD and 1 on DD.
277281464ebSragge  */
278281464ebSragge int rfcprobedens(struct rfc_softc *, int);
279281464ebSragge int
rfcprobedens(struct rfc_softc * rfc_sc,int dnum)280281464ebSragge rfcprobedens(struct rfc_softc *rfc_sc, int dnum)
281281464ebSragge {
282281464ebSragge 	int dens_flag;
283281464ebSragge 	int i;
284281464ebSragge 
285281464ebSragge 	dens_flag = 0;
286281464ebSragge 	do {
287281464ebSragge 		bus_space_write_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS,
288281464ebSragge 		    RX2CS_RSEC | (dens_flag == 0 ? 0 : RX2CS_DD)
289281464ebSragge 		    | (dnum == 0 ? 0 : RX2CS_US));
290281464ebSragge 		/*
291281464ebSragge 		 * Transfer request set?
292281464ebSragge 		 * Wait 50us, the controller needs this time to setle
293281464ebSragge 		 */
294281464ebSragge 		DELAY(50);
295281464ebSragge 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
296281464ebSragge 		    & RX2CS_TR) == 0) {
297281464ebSragge 			printf("%s: did not respond to Read Sector CMD(1)\n",
298dfba8166Smatt 			    device_xname(rfc_sc->sc_dev));
299281464ebSragge 			return(-1);
300281464ebSragge 		}
301281464ebSragge 		bus_space_write_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2SA, 1);
302281464ebSragge 		/* Wait 50us, the controller needs this time to setle */
303281464ebSragge 		DELAY(50);
304281464ebSragge 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
305281464ebSragge 		    & RX2CS_TR) == 0) {
306281464ebSragge 			printf("%s: did not respond to Read Sector CMD(2)\n",
307dfba8166Smatt 			    device_xname(rfc_sc->sc_dev));
308281464ebSragge 			return(-1);
309281464ebSragge 		}
310281464ebSragge 		bus_space_write_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2TA, 1);
311281464ebSragge 		/* Wait for the command to finish */
312281464ebSragge 		for (i = 0 ; i < 200 ; i++) {
313281464ebSragge 			if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh,
314281464ebSragge 			    RX2CS) & RX2CS_DONE) != 0)
315281464ebSragge 				break;
316281464ebSragge 			DELAY(10000);	/* wait 10ms */
317281464ebSragge 		}
318281464ebSragge 		if (i >= 200) {
319281464ebSragge 			printf("%s: did not respond to Read Sector CMD(3)\n",
320dfba8166Smatt 			    device_xname(rfc_sc->sc_dev));
321281464ebSragge 			return(-1);
322281464ebSragge 		}
323281464ebSragge 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
324281464ebSragge 		    & RX2CS_ERR) == 0)
325281464ebSragge 			return(dens_flag);
326281464ebSragge 	} while (rfc_sc->type == 2 && dens_flag++ == 0);
327281464ebSragge 	return(-1);
328281464ebSragge }
329281464ebSragge #endif /* RX02_PROBE */
330281464ebSragge 
331281464ebSragge 
332281464ebSragge 
333281464ebSragge void
rfc_attach(device_t parent,device_t self,void * aux)334dfba8166Smatt rfc_attach(device_t parent, device_t self, void *aux)
335281464ebSragge {
336ceb94256Sthorpej 	struct rfc_softc *rfc_sc = device_private(self);
337281464ebSragge 	struct uba_attach_args *ua = aux;
338281464ebSragge 	struct rfc_attach_args rfc_aa;
339281464ebSragge 	int i;
340281464ebSragge 
341dfba8166Smatt 	rfc_sc->sc_dev = self;
342281464ebSragge 	rfc_sc->sc_iot = ua->ua_iot;
343281464ebSragge 	rfc_sc->sc_ioh = ua->ua_ioh;
344281464ebSragge 	rfc_sc->sc_dmat = ua->ua_dmat;
345281464ebSragge 	rfc_sc->sc_curbuf = NULL;
346281464ebSragge 	/* Tell the QBus busdriver about our interrupt handler. */
347281464ebSragge 	uba_intr_establish(ua->ua_icookie, ua->ua_cvec, rfc_intr, rfc_sc,
348281464ebSragge 	    &rfc_sc->sc_intr_count);
349281464ebSragge 	/* Attach to the interrupt counter, see evcnt(9) */
350281464ebSragge 	evcnt_attach_dynamic(&rfc_sc->sc_intr_count, EVCNT_TYPE_INTR,
351dfba8166Smatt 	    ua->ua_evcnt, device_xname(rfc_sc->sc_dev), "intr");
352281464ebSragge 	/* get a bus_dma(9) handle */
353281464ebSragge 	i = bus_dmamap_create(rfc_sc->sc_dmat, RX2_BYTE_DD, 1, RX2_BYTE_DD, 0,
354281464ebSragge 	    BUS_DMA_ALLOCNOW, &rfc_sc->sc_dmam);
355281464ebSragge 	if (i != 0) {
356c049e276Sragge 		printf("rfc_attach: Error creating bus dma map: %d\n", i);
357281464ebSragge 		return;
358281464ebSragge 	}
359281464ebSragge 
360281464ebSragge 	/* Issue reset command. */
361281464ebSragge 	bus_space_write_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS, RX2CS_INIT);
362281464ebSragge 	/*
363281464ebSragge 	 * Wait for the controller to become ready, that is when
364281464ebSragge 	 * RX2CS_DONE, RX2ES_RDY and RX2ES_ID are set.
365281464ebSragge 	 */
366281464ebSragge 	for (i = 0 ; i < 20 ; i++) {
367281464ebSragge 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
368281464ebSragge 		    & RX2CS_DONE) != 0
369281464ebSragge 		    && (bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2ES)
370281464ebSragge 		    & (RX2ES_RDY | RX2ES_ID)) != 0)
371281464ebSragge 			break;
372281464ebSragge 		DELAY(100000);	/* wait 100ms */
373281464ebSragge 	}
374281464ebSragge 	/*
375281464ebSragge 	 * Give up if the timeout has elapsed
376281464ebSragge 	 * and the controller is not ready.
377281464ebSragge 	 */
378281464ebSragge 	if (i >= 20) {
379281464ebSragge 		printf(": did not respond to INIT CMD\n");
380281464ebSragge 		return;
381281464ebSragge 	}
382281464ebSragge 	/* Is ths a RX01 or a RX02? */
383281464ebSragge 	if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
384281464ebSragge 	    & RX2CS_RX02) != 0) {
385281464ebSragge 		rfc_sc->type = 2;
386281464ebSragge 		rfc_aa.type = 2;
387281464ebSragge 	} else {
388281464ebSragge 		rfc_sc->type = 1;
389281464ebSragge 		rfc_aa.type = 1;
390281464ebSragge 	}
391281464ebSragge 	printf(": RX0%d\n", rfc_sc->type);
392281464ebSragge 
393281464ebSragge #ifndef RX02_PROBE
394281464ebSragge 	/*
395*38ad5e0eSandvar 	 * Both disk drives and the controller are one physical unit.
396*38ad5e0eSandvar 	 * If we found the controller, there will be both disk drives.
397281464ebSragge 	 * So attach them.
398281464ebSragge 	 */
399281464ebSragge 	rfc_aa.dnum = 0;
4002685996bSthorpej 	rfc_sc->sc_childs[0] = config_found(rfc_sc->sc_dev, &rfc_aa, rf_print,
401c7fb772bSthorpej 	    CFARGS_NONE);
402281464ebSragge 	rfc_aa.dnum = 1;
4032685996bSthorpej 	rfc_sc->sc_childs[1] = config_found(rfc_sc->sc_dev, &rfc_aa, rf_print,
404c7fb772bSthorpej 	    CFARGS_NONE);
405281464ebSragge #else /* RX02_PROBE */
406281464ebSragge 	/*
407281464ebSragge 	 * There are clones of the DEC RX system with standard shugart
408281464ebSragge 	 * interface. In this case we can not be sure that there are
409*38ad5e0eSandvar 	 * both disk drives. So we want to do a detection of attached
410281464ebSragge 	 * drives. This is done by reading a sector from disk. This means
4119876532dSwiz 	 * that there must be a formatted disk in the drive at boot time.
412281464ebSragge 	 * This is bad, but I did not find another way to detect the
413281464ebSragge 	 * (non)existence of a floppy drive.
414281464ebSragge 	 */
415281464ebSragge 	if (rfcprobedens(rfc_sc, 0) >= 0) {
416281464ebSragge 		rfc_aa.dnum = 0;
417cbab9cadSchs 		rfc_sc->sc_childs[0] = config_found(rfc_sc->sc_dev, &rfc_aa,
418c7fb772bSthorpej 		    rf_print, CFARGS_NONE);
419281464ebSragge 	} else
420281464ebSragge 		rfc_sc->sc_childs[0] = NULL;
421281464ebSragge 	if (rfcprobedens(rfc_sc, 1) >= 0) {
422281464ebSragge 		rfc_aa.dnum = 1;
423cbab9cadSchs 		rfc_sc->sc_childs[1] = config_found(rfc_sc->sc_dev, &rfc_aa,
424c7fb772bSthorpej 		    rf_print, CFARGS_NONE);
425281464ebSragge 	} else
426281464ebSragge 		rfc_sc->sc_childs[1] = NULL;
427281464ebSragge #endif /* RX02_PROBE */
428281464ebSragge 	return;
429281464ebSragge }
430281464ebSragge 
431281464ebSragge 
432281464ebSragge 
433281464ebSragge int
rf_match(device_t parent,cfdata_t match,void * aux)434dfba8166Smatt rf_match(device_t parent, cfdata_t match, void *aux)
435281464ebSragge {
436281464ebSragge 	struct rfc_attach_args *rfc_aa = aux;
437281464ebSragge 
438281464ebSragge 	/*
439281464ebSragge 	 * Only attach if the locator is wildcarded or
440281464ebSragge 	 * if the specified locator addresses the current device.
441281464ebSragge 	 */
442281464ebSragge 	if (match->cf_loc[RFCCF_DRIVE] == RFCCF_DRIVE_DEFAULT ||
443281464ebSragge 	    match->cf_loc[RFCCF_DRIVE] == rfc_aa->dnum)
444281464ebSragge 		return(1);
445281464ebSragge 	return(0);
446281464ebSragge }
447281464ebSragge 
448281464ebSragge 
449281464ebSragge 
450281464ebSragge void
rf_attach(device_t parent,device_t self,void * aux)451dfba8166Smatt rf_attach(device_t parent, device_t self, void *aux)
452281464ebSragge {
453ceb94256Sthorpej 	struct rf_softc *rf_sc = device_private(self);
454dfba8166Smatt 	struct rfc_softc *rfc_sc = device_private(parent);
455281464ebSragge 	struct rfc_attach_args *rfc_aa = (struct rfc_attach_args *)aux;
456281464ebSragge 	struct disklabel *dl;
457281464ebSragge 
458dfba8166Smatt 	rf_sc->sc_dev = self;
459dfba8166Smatt 	rf_sc->sc_rfc = rfc_sc;
460281464ebSragge 	rf_sc->sc_dnum = rfc_aa->dnum;
461281464ebSragge 	rf_sc->sc_state = 0;
462dfba8166Smatt 	disk_init(&rf_sc->sc_disk, device_xname(rf_sc->sc_dev), &rfdkdriver);
463281464ebSragge 	disk_attach(&rf_sc->sc_disk);
464281464ebSragge 	dl = rf_sc->sc_disk.dk_label;
465c182898bSchristos 	dl->d_type = DKTYPE_FLOPPY;		/* drive type */
466281464ebSragge 	dl->d_magic = DISKMAGIC;		/* the magic number */
467281464ebSragge 	dl->d_magic2 = DISKMAGIC;
468281464ebSragge 	dl->d_typename[0] = 'R';
469281464ebSragge 	dl->d_typename[1] = 'X';
470281464ebSragge 	dl->d_typename[2] = '0';
471281464ebSragge 	dl->d_typename[3] = rfc_sc->type == 1 ? '1' : '2';	/* type name */
472281464ebSragge 	dl->d_typename[4] = '\0';
473281464ebSragge 	dl->d_secsize = DEV_BSIZE;		/* bytes per sector */
474281464ebSragge 	/*
475*38ad5e0eSandvar 	 * Fill in some values to have an initialized data structure. Some
476281464ebSragge 	 * values will be reset by rfopen() depending on the actual density.
477281464ebSragge 	 */
478281464ebSragge 	dl->d_nsectors = RX2_SECTORS;		/* sectors per track */
479281464ebSragge 	dl->d_ntracks = 1;								/* tracks per cylinder */
480281464ebSragge 	dl->d_ncylinders = RX2_TRACKS;		/* cylinders per unit */
481281464ebSragge 	dl->d_secpercyl = RX2_SECTORS;		/* sectors per cylinder */
482281464ebSragge 	dl->d_secperunit = RX2_SECTORS * RX2_TRACKS;	/* sectors per unit */
483281464ebSragge 	dl->d_rpm = 360;			/* rotational speed */
484281464ebSragge 	dl->d_interleave = 1;			/* hardware sector interleave */
485281464ebSragge 	/* number of partitions in following */
486281464ebSragge 	dl->d_npartitions = MAXPARTITIONS;
487281464ebSragge 	dl->d_bbsize = 0;		/* size of boot area at sn0, bytes */
488281464ebSragge 	dl->d_sbsize = 0;		/* max size of fs superblock, bytes */
489281464ebSragge 	/* number of sectors in partition */
490281464ebSragge 	dl->d_partitions[0].p_size = 501;
491281464ebSragge 	dl->d_partitions[0].p_offset = 0;	/* starting sector */
492281464ebSragge 	dl->d_partitions[0].p_fsize = 0;	/* fs basic fragment size */
493281464ebSragge 	dl->d_partitions[0].p_fstype = 0;	/* fs type */
494281464ebSragge 	dl->d_partitions[0].p_frag = 0;		/* fs fragments per block */
495281464ebSragge 	dl->d_partitions[1].p_size = RX2_SECTORS * RX2_TRACKS / 2;
496281464ebSragge 	dl->d_partitions[1].p_offset = 0;	/* starting sector */
497281464ebSragge 	dl->d_partitions[1].p_fsize = 0;	/* fs basic fragment size */
498281464ebSragge 	dl->d_partitions[1].p_fstype = 0;	/* fs type */
499281464ebSragge 	dl->d_partitions[1].p_frag = 0;		/* fs fragments per block */
500281464ebSragge 	dl->d_partitions[2].p_size = RX2_SECTORS * RX2_TRACKS;
501281464ebSragge 	dl->d_partitions[2].p_offset = 0;	/* starting sector */
502281464ebSragge 	dl->d_partitions[2].p_fsize = 0;	/* fs basic fragment size */
503281464ebSragge 	dl->d_partitions[2].p_fstype = 0;	/* fs type */
504281464ebSragge 	dl->d_partitions[2].p_frag = 0;		/* fs fragments per block */
505aec75b1cSyamt 	bufq_alloc(&rf_sc->sc_bufq, "disksort", BUFQ_SORT_CYLINDER);
506281464ebSragge 	printf("\n");
507281464ebSragge 	return;
508281464ebSragge }
509281464ebSragge 
510281464ebSragge 
511281464ebSragge 
512281464ebSragge int
rf_print(void * aux,const char * name)513281464ebSragge rf_print(void *aux, const char *name)
514281464ebSragge {
515281464ebSragge 	struct rfc_attach_args *rfc_aa = aux;
516281464ebSragge 
517281464ebSragge 	if (name != NULL)
518281464ebSragge 		aprint_normal("RX0%d at %s", rfc_aa->type, name);
519281464ebSragge 	aprint_normal(" drive %d", rfc_aa->dnum);
520281464ebSragge 	return(UNCONF);
521281464ebSragge }
522281464ebSragge 
523281464ebSragge 
524281464ebSragge 
525281464ebSragge /* Send a command to the controller */
526281464ebSragge int
rfc_sendcmd(struct rfc_softc * rfc_sc,int cmd,int data1,int data2)527281464ebSragge rfc_sendcmd(struct rfc_softc *rfc_sc, int cmd, int data1, int data2)
528281464ebSragge {
529281464ebSragge 
530281464ebSragge 	/* Write command to CSR. */
531281464ebSragge 	bus_space_write_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS, cmd);
532281464ebSragge 	/* Wait 50us, the controller needs this time to setle. */
533281464ebSragge 	DELAY(50);
534281464ebSragge 	/* Write parameter 1 to DBR */
5352e741b3aSchristos 	if ((cmd & RX2CS_MASK) != RX2CS_RSTAT) {
536281464ebSragge 		/* Transfer request set? */
537281464ebSragge 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
538281464ebSragge 		    & RX2CS_TR) == 0) {
539281464ebSragge 			printf("%s: did not respond to CMD %x (1)\n",
540dfba8166Smatt 			    device_xname(rfc_sc->sc_dev), cmd);
541281464ebSragge 			return(-1);
542281464ebSragge 		}
543281464ebSragge 		bus_space_write_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2DB,
544281464ebSragge 		    data1);
545281464ebSragge 	}
546281464ebSragge 	/* Write parameter 2 to DBR */
5472e741b3aSchristos 	if ((cmd & RX2CS_MASK) <= RX2CS_RSEC ||
5482e741b3aSchristos 	    (cmd & RX2CS_MASK) == RX2CS_WDDS) {
549281464ebSragge 		/* Wait 50us, the controller needs this time to setle. */
550281464ebSragge 		DELAY(50);
551281464ebSragge 		/* Transfer request set? */
552281464ebSragge 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
553281464ebSragge 		    & RX2CS_TR) == 0) {
554281464ebSragge 			printf("%s: did not respond to CMD %x (2)\n",
555dfba8166Smatt 			    device_xname(rfc_sc->sc_dev), cmd);
556281464ebSragge 			return(-1);
557281464ebSragge 		}
558281464ebSragge 		bus_space_write_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2DB,
559281464ebSragge 		    data2);
560281464ebSragge 	}
561281464ebSragge 	return(1);
562281464ebSragge }
563281464ebSragge 
564281464ebSragge 
565281464ebSragge 
566281464ebSragge void
rfstrategy(struct buf * buf)567281464ebSragge rfstrategy(struct buf *buf)
568281464ebSragge {
569281464ebSragge 	struct rf_softc *rf_sc;
570281464ebSragge 	struct rfc_softc *rfc_sc;
571dfba8166Smatt 	int s;
572281464ebSragge 
573dfba8166Smatt 	if ((rf_sc = device_lookup_private(&rf_cd, DISKUNIT(buf->b_dev))) == NULL) {
574281464ebSragge 		buf->b_error = ENXIO;
575281464ebSragge 		biodone(buf);
576281464ebSragge 		return;
577281464ebSragge 	}
578dfba8166Smatt 	rfc_sc = rf_sc->sc_rfc;
5799876532dSwiz 	/* We are going to operate on a non-open dev? PANIC! */
580dfba8166Smatt 	if ((rf_sc->sc_state & (1 << (DISKPART(buf->b_dev) + RFS_OPEN_SHIFT)))
581c049e276Sragge 	    == 0)
582c049e276Sragge 		panic("rfstrategy: can not operate on non-open drive %s "
58323efc364Scegger 		    "partition %"PRIu32, device_xname(rf_sc->sc_dev),
584c049e276Sragge 		    DISKPART(buf->b_dev));
585281464ebSragge 	if (buf->b_bcount == 0) {
586281464ebSragge 		biodone(buf);
587281464ebSragge 		return;
588281464ebSragge 	}
589281464ebSragge 	/*
59070de9736Syamt 	 * bufq_put() operates on b_rawblkno. rfstrategy() gets
591281464ebSragge 	 * only b_blkno that is partition relative. As a floppy does not
592281464ebSragge 	 * have partitions b_rawblkno == b_blkno.
593281464ebSragge 	 */
594281464ebSragge 	buf->b_rawblkno = buf->b_blkno;
595281464ebSragge 	/*
596281464ebSragge 	 * from sys/kern/subr_disk.c:
597281464ebSragge 	 * Seek sort for disks.  We depend on the driver which calls us using
598281464ebSragge 	 * b_resid as the current cylinder number.
599281464ebSragge 	 */
600dfba8166Smatt 	s = splbio();
601281464ebSragge 	if (rfc_sc->sc_curbuf == NULL) {
602281464ebSragge 		rfc_sc->sc_curchild = rf_sc->sc_dnum;
603281464ebSragge 		rfc_sc->sc_curbuf = buf;
604e36a3212Sjoerg 		rfc_sc->sc_bufidx = buf->b_data;
605281464ebSragge 		rfc_sc->sc_bytesleft = buf->b_bcount;
606281464ebSragge 		rfc_intr(rfc_sc);
607281464ebSragge 	} else {
608281464ebSragge 		buf->b_resid = buf->b_blkno / RX2_SECTORS;
60970de9736Syamt 		bufq_put(rf_sc->sc_bufq, buf);
610c049e276Sragge 		buf->b_resid = 0;
611281464ebSragge 	}
612dfba8166Smatt 	splx(s);
613281464ebSragge }
614281464ebSragge 
615c049e276Sragge /*
616c049e276Sragge  * Look if there is another buffer in the bufferqueue of this drive
617c049e276Sragge  * and start to process it if there is one.
618c049e276Sragge  * If the bufferqueue is empty, look at the bufferqueue of the other drive
619c049e276Sragge  * that is attached to this controller.
620*38ad5e0eSandvar  * Start processing the bufferqueue of the other drive if it isn't empty.
621c049e276Sragge  * Return a pointer to the softc structure of the drive that is now
622c049e276Sragge  * ready to process a buffer or NULL if there is no buffer in either queues.
623c049e276Sragge  */
624c049e276Sragge struct rf_softc*
get_new_buf(struct rfc_softc * rfc_sc)625c049e276Sragge get_new_buf( struct rfc_softc *rfc_sc)
626c049e276Sragge {
627c049e276Sragge 	struct rf_softc *rf_sc;
628c049e276Sragge 	struct rf_softc *other_drive;
629c049e276Sragge 
6306827de95Sjkunz 	rf_sc = device_private(rfc_sc->sc_childs[rfc_sc->sc_curchild]);
63170de9736Syamt 	rfc_sc->sc_curbuf = bufq_get(rf_sc->sc_bufq);
632c049e276Sragge 	if (rfc_sc->sc_curbuf != NULL) {
633e36a3212Sjoerg 		rfc_sc->sc_bufidx = rfc_sc->sc_curbuf->b_data;
634c049e276Sragge 		rfc_sc->sc_bytesleft = rfc_sc->sc_curbuf->b_bcount;
635c049e276Sragge 	} else {
636c049e276Sragge 		RFS_SETCMD(rf_sc->sc_state, RFS_IDLE);
6376827de95Sjkunz 		other_drive = device_private(
6386827de95Sjkunz 		    rfc_sc->sc_childs[ rfc_sc->sc_curchild == 0 ? 1 : 0]);
639c049e276Sragge 		if (other_drive != NULL
64070de9736Syamt 		    && bufq_peek(other_drive->sc_bufq) != NULL) {
641c049e276Sragge 			rfc_sc->sc_curchild = rfc_sc->sc_curchild == 0 ? 1 : 0;
642c049e276Sragge 			rf_sc = other_drive;
64370de9736Syamt 			rfc_sc->sc_curbuf = bufq_get(rf_sc->sc_bufq);
644e36a3212Sjoerg 			rfc_sc->sc_bufidx = rfc_sc->sc_curbuf->b_data;
645c049e276Sragge 			rfc_sc->sc_bytesleft = rfc_sc->sc_curbuf->b_bcount;
646c049e276Sragge 		} else
647c049e276Sragge 			return(NULL);
648c049e276Sragge 	}
649c049e276Sragge 	return(rf_sc);
650c049e276Sragge }
651c049e276Sragge 
652c049e276Sragge 
653c049e276Sragge 
654281464ebSragge void
rfc_intr(void * intarg)655281464ebSragge rfc_intr(void *intarg)
656281464ebSragge {
657281464ebSragge 	struct rfc_softc *rfc_sc = intarg;
658281464ebSragge 	struct rf_softc *rf_sc;
659281464ebSragge 	int i;
660281464ebSragge 
6616827de95Sjkunz 	rf_sc = device_private(rfc_sc->sc_childs[rfc_sc->sc_curchild]);
662bc2387e2Sdsl 	for (;;) {
663281464ebSragge 		/*
664281464ebSragge 		 * First clean up from previous command...
665281464ebSragge 		 */
666281464ebSragge 		switch (rf_sc->sc_state & RFS_CMDS) {
667281464ebSragge 		case RFS_PROBING:	/* density detect / verify started */
668281464ebSragge 			disk_unbusy(&rf_sc->sc_disk, 0, 1);
669c049e276Sragge 			if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh,
670c049e276Sragge 			    RX2CS) & RX2CS_ERR) == 0) {
671281464ebSragge 				RFS_SETCMD(rf_sc->sc_state, RFS_IDLE);
672281464ebSragge 				wakeup(rf_sc);
673281464ebSragge 			} else {
674281464ebSragge 				if (rfc_sc->type == 2
675281464ebSragge 				    && (rf_sc->sc_state & RFS_DENS) == 0
676281464ebSragge 				    && (rf_sc->sc_state & RFS_AD) != 0) {
677281464ebSragge 					/* retry at DD */
678281464ebSragge 					rf_sc->sc_state |= RFS_DENS;
679281464ebSragge 					disk_busy(&rf_sc->sc_disk);
680c049e276Sragge 					if (rfc_sendcmd(rfc_sc, RX2CS_RSEC
681c049e276Sragge 					    | RX2CS_IE | RX2CS_DD |
682c049e276Sragge 					    (rf_sc->sc_dnum == 0 ? 0 :
683c049e276Sragge 					    RX2CS_US), 1, 1) < 0) {
684c049e276Sragge 						disk_unbusy(&rf_sc->sc_disk,
685c049e276Sragge 						    0, 1);
686281464ebSragge 						RFS_SETCMD(rf_sc->sc_state,
687281464ebSragge 						    RFS_NOTINIT);
688281464ebSragge 						wakeup(rf_sc);
689281464ebSragge 					}
690281464ebSragge 				} else {
691281464ebSragge 					printf("%s: density error.\n",
692dfba8166Smatt 					    device_xname(rf_sc->sc_dev));
693281464ebSragge 					RFS_SETCMD(rf_sc->sc_state,RFS_NOTINIT);
694281464ebSragge 					wakeup(rf_sc);
695281464ebSragge 				}
696281464ebSragge 			}
697281464ebSragge 			return;
698281464ebSragge 		case RFS_IDLE:	/* controller is idle */
699281464ebSragge 			if (rfc_sc->sc_curbuf->b_bcount
700281464ebSragge 			    % ((rf_sc->sc_state & RFS_DENS) == 0
701281464ebSragge 			    ? RX2_BYTE_SD : RX2_BYTE_DD) != 0) {
702281464ebSragge 				/*
703c049e276Sragge 				 * can only handle blocks that are a multiple
704c049e276Sragge 				 * of the physical block size
705281464ebSragge 				 */
70666fefd11Sad 				rfc_sc->sc_curbuf->b_error = EIO;
707281464ebSragge 			}
708281464ebSragge 			RFS_SETCMD(rf_sc->sc_state, (rfc_sc->sc_curbuf->b_flags
709281464ebSragge 			    & B_READ) != 0 ? RFS_RSEC : RFS_FBUF);
710281464ebSragge 			break;
711281464ebSragge 		case RFS_RSEC:	/* Read Sector */
712281464ebSragge 			disk_unbusy(&rf_sc->sc_disk, 0, 1);
713281464ebSragge 			/* check for errors */
714c049e276Sragge 			if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh,
715c049e276Sragge 			    RX2CS) & RX2CS_ERR) != 0) {
716281464ebSragge 				/* should do more verbose error reporting */
717c049e276Sragge 				printf("rfc_intr: Error reading secotr: %x\n",
718281464ebSragge 				    bus_space_read_2(rfc_sc->sc_iot,
719281464ebSragge 				    rfc_sc->sc_ioh, RX2ES) );
72066fefd11Sad 				rfc_sc->sc_curbuf->b_error = EIO;
721281464ebSragge 			}
722281464ebSragge 			RFS_SETCMD(rf_sc->sc_state, RFS_EBUF);
723281464ebSragge 			break;
724281464ebSragge 		case RFS_WSEC:	/* Write Sector */
725281464ebSragge 			i = (rf_sc->sc_state & RFS_DENS) == 0
726281464ebSragge 				? RX2_BYTE_SD : RX2_BYTE_DD;
727281464ebSragge 			disk_unbusy(&rf_sc->sc_disk, i, 0);
728281464ebSragge 			/* check for errors */
729c049e276Sragge 			if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh,
730c049e276Sragge 			    RX2CS) & RX2CS_ERR) != 0) {
731281464ebSragge 				/* should do more verbose error reporting */
732c049e276Sragge 				printf("rfc_intr: Error writing secotr: %x\n",
733281464ebSragge 				    bus_space_read_2(rfc_sc->sc_iot,
734281464ebSragge 				    rfc_sc->sc_ioh, RX2ES) );
73566fefd11Sad 				rfc_sc->sc_curbuf->b_error = EIO;
736281464ebSragge 				break;
737281464ebSragge 			}
738281464ebSragge 			if (rfc_sc->sc_bytesleft > i) {
739281464ebSragge 				rfc_sc->sc_bytesleft -= i;
740bf9a718bShe 				rfc_sc->sc_bufidx =
741bf9a718bShe 				    (char *)rfc_sc->sc_bufidx + i;
742281464ebSragge 			} else {
743281464ebSragge 				biodone(rfc_sc->sc_curbuf);
744c049e276Sragge 				rf_sc = get_new_buf( rfc_sc);
745c049e276Sragge 				if (rf_sc == NULL)
746281464ebSragge 					return;
747281464ebSragge 			}
748281464ebSragge 			RFS_SETCMD(rf_sc->sc_state,
749281464ebSragge 			    (rfc_sc->sc_curbuf->b_flags & B_READ) != 0
750281464ebSragge 			    ? RFS_RSEC : RFS_FBUF);
751281464ebSragge 			break;
752281464ebSragge 		case RFS_FBUF:	/* Fill Buffer */
753281464ebSragge 			disk_unbusy(&rf_sc->sc_disk, 0, 0);
754c049e276Sragge 			bus_dmamap_unload(rfc_sc->sc_dmat, rfc_sc->sc_dmam);
755281464ebSragge 			/* check for errors */
756c049e276Sragge 			if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh,
757c049e276Sragge 			    RX2CS) & RX2CS_ERR) != 0) {
758281464ebSragge 				/* should do more verbose error reporting */
759281464ebSragge 				printf("rfc_intr: Error while DMA: %x\n",
760281464ebSragge 				    bus_space_read_2(rfc_sc->sc_iot,
761281464ebSragge 				    rfc_sc->sc_ioh, RX2ES));
76266fefd11Sad 				rfc_sc->sc_curbuf->b_error = EIO;
763281464ebSragge 			}
764281464ebSragge 			RFS_SETCMD(rf_sc->sc_state, RFS_WSEC);
765281464ebSragge 			break;
766281464ebSragge 		case RFS_EBUF:	/* Empty Buffer */
767281464ebSragge 			i = (rf_sc->sc_state & RFS_DENS) == 0
768281464ebSragge 			    ? RX2_BYTE_SD : RX2_BYTE_DD;
769281464ebSragge 			disk_unbusy(&rf_sc->sc_disk, i, 1);
770c049e276Sragge 			bus_dmamap_unload(rfc_sc->sc_dmat, rfc_sc->sc_dmam);
771281464ebSragge 			/* check for errors */
772c049e276Sragge 			if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh,
773c049e276Sragge 			    RX2CS) & RX2CS_ERR) != 0) {
774281464ebSragge 				/* should do more verbose error reporting */
775281464ebSragge 				printf("rfc_intr: Error while DMA: %x\n",
776281464ebSragge 				    bus_space_read_2(rfc_sc->sc_iot,
777281464ebSragge 				    rfc_sc->sc_ioh, RX2ES));
77866fefd11Sad 				rfc_sc->sc_curbuf->b_error = EIO;
779c049e276Sragge 				break;
780281464ebSragge 			}
781281464ebSragge 			if (rfc_sc->sc_bytesleft > i) {
782281464ebSragge 				rfc_sc->sc_bytesleft -= i;
783bf9a718bShe 				rfc_sc->sc_bufidx =
784bf9a718bShe 				    (char *)rfc_sc->sc_bufidx + i;
785281464ebSragge 			} else {
786281464ebSragge 				biodone(rfc_sc->sc_curbuf);
787c049e276Sragge 				rf_sc = get_new_buf( rfc_sc);
788c049e276Sragge 				if (rf_sc == NULL)
789281464ebSragge 					return;
790281464ebSragge 			}
791281464ebSragge 			RFS_SETCMD(rf_sc->sc_state,
792281464ebSragge 			    (rfc_sc->sc_curbuf->b_flags & B_READ) != 0
793281464ebSragge 			    ? RFS_RSEC : RFS_FBUF);
794281464ebSragge 			break;
795c049e276Sragge 		case RFS_NOTINIT: /* Device is not open */
796281464ebSragge 		case RFS_SMD:	/* Set Media Density */
797281464ebSragge 		case RFS_RSTAT:	/* Read Status */
798281464ebSragge 		case RFS_WDDS:	/* Write Deleted Data Sector */
799281464ebSragge 		case RFS_REC:	/* Read Error Code */
800281464ebSragge 		default:
8016827de95Sjkunz 			panic("Impossible state in rfc_intr(1): 0x%x\n",
8026827de95Sjkunz 			    rf_sc->sc_state & RFS_CMDS);
803281464ebSragge 		}
804281464ebSragge 
80566fefd11Sad 		if (rfc_sc->sc_curbuf->b_error != 0) {
806c049e276Sragge 			/*
807f05e6f1aSwiz 			 * An error occurred while processing this buffer.
808c049e276Sragge 			 * Finish it and try to get a new buffer to process.
809c049e276Sragge 			 * Return if there are no buffers in the queues.
810c049e276Sragge 			 * This loops until the queues are empty or a new
811c049e276Sragge 			 * action was successfully scheduled.
812c049e276Sragge 			 */
813c049e276Sragge 			rfc_sc->sc_curbuf->b_resid = rfc_sc->sc_bytesleft;
814281464ebSragge 			rfc_sc->sc_curbuf->b_error = EIO;
815281464ebSragge 			biodone(rfc_sc->sc_curbuf);
816c049e276Sragge 			rf_sc = get_new_buf( rfc_sc);
817c049e276Sragge 			if (rf_sc == NULL)
818281464ebSragge 				return;
819c049e276Sragge 			continue;
820281464ebSragge 		}
821281464ebSragge 
822281464ebSragge 		/*
823281464ebSragge 		 * ... then initiate next command.
824281464ebSragge 		 */
825281464ebSragge 		switch (rf_sc->sc_state & RFS_CMDS) {
826281464ebSragge 		case RFS_EBUF:	/* Empty Buffer */
827281464ebSragge 			i = bus_dmamap_load(rfc_sc->sc_dmat, rfc_sc->sc_dmam,
828281464ebSragge 			    rfc_sc->sc_bufidx, (rf_sc->sc_state & RFS_DENS) == 0
829c049e276Sragge 			    ? RX2_BYTE_SD : RX2_BYTE_DD,
830c049e276Sragge 			    rfc_sc->sc_curbuf->b_proc, BUS_DMA_NOWAIT);
831281464ebSragge 			if (i != 0) {
832c049e276Sragge 				printf("rfc_intr: Error loading dmamap: %d\n",
833c049e276Sragge 				i);
83466fefd11Sad 				rfc_sc->sc_curbuf->b_error = EIO;
835281464ebSragge 				break;
836281464ebSragge 			}
837281464ebSragge 			disk_busy(&rf_sc->sc_disk);
838281464ebSragge 			if (rfc_sendcmd(rfc_sc, RX2CS_EBUF | RX2CS_IE
839281464ebSragge 			    | ((rf_sc->sc_state & RFS_DENS) == 0 ? 0 : RX2CS_DD)
840281464ebSragge 			    | (rf_sc->sc_dnum == 0 ? 0 : RX2CS_US)
841c049e276Sragge 			    | ((rfc_sc->sc_dmam->dm_segs[0].ds_addr
842c049e276Sragge 			    & 0x30000) >>4), ((rf_sc->sc_state & RFS_DENS) == 0
843281464ebSragge 			    ? RX2_BYTE_SD : RX2_BYTE_DD) / 2,
844281464ebSragge 			    rfc_sc->sc_dmam->dm_segs[0].ds_addr & 0xffff) < 0) {
845c049e276Sragge 				disk_unbusy(&rf_sc->sc_disk, 0, 1);
84666fefd11Sad 				rfc_sc->sc_curbuf->b_error = EIO;
847c049e276Sragge 				bus_dmamap_unload(rfc_sc->sc_dmat,
848c049e276Sragge 				rfc_sc->sc_dmam);
849281464ebSragge 			}
850281464ebSragge 			break;
851281464ebSragge 		case RFS_FBUF:	/* Fill Buffer */
852281464ebSragge 			i = bus_dmamap_load(rfc_sc->sc_dmat, rfc_sc->sc_dmam,
853281464ebSragge 			    rfc_sc->sc_bufidx, (rf_sc->sc_state & RFS_DENS) == 0
854281464ebSragge 			    ? RX2_BYTE_SD : RX2_BYTE_DD,
855281464ebSragge 			    rfc_sc->sc_curbuf->b_proc, BUS_DMA_NOWAIT);
856281464ebSragge 			if (i != 0) {
857c049e276Sragge 				printf("rfc_intr: Error loading dmamap: %d\n",
858c049e276Sragge 				    i);
85966fefd11Sad 				rfc_sc->sc_curbuf->b_error = EIO;
860281464ebSragge 				break;
861281464ebSragge 			}
862281464ebSragge 			disk_busy(&rf_sc->sc_disk);
863281464ebSragge 			if (rfc_sendcmd(rfc_sc, RX2CS_FBUF | RX2CS_IE
864281464ebSragge 			    | ((rf_sc->sc_state & RFS_DENS) == 0 ? 0 : RX2CS_DD)
865281464ebSragge 			    | (rf_sc->sc_dnum == 0 ? 0 : RX2CS_US)
866c049e276Sragge 			    | ((rfc_sc->sc_dmam->dm_segs[0].ds_addr
867c049e276Sragge 			    & 0x30000)>>4), ((rf_sc->sc_state & RFS_DENS) == 0
868281464ebSragge 			    ? RX2_BYTE_SD : RX2_BYTE_DD) / 2,
869281464ebSragge 			    rfc_sc->sc_dmam->dm_segs[0].ds_addr & 0xffff) < 0) {
870c049e276Sragge 				disk_unbusy(&rf_sc->sc_disk, 0, 0);
87166fefd11Sad 				rfc_sc->sc_curbuf->b_error = EIO;
872c049e276Sragge 				bus_dmamap_unload(rfc_sc->sc_dmat,
873c049e276Sragge 				    rfc_sc->sc_dmam);
874281464ebSragge 			}
875281464ebSragge 			break;
876281464ebSragge 		case RFS_WSEC:	/* Write Sector */
877281464ebSragge 			i = (rfc_sc->sc_curbuf->b_bcount - rfc_sc->sc_bytesleft
878281464ebSragge 			    + rfc_sc->sc_curbuf->b_blkno * DEV_BSIZE) /
879281464ebSragge 			    ((rf_sc->sc_state & RFS_DENS) == 0
880281464ebSragge 			    ? RX2_BYTE_SD : RX2_BYTE_DD);
881281464ebSragge 			if (i > RX2_TRACKS * RX2_SECTORS) {
88266fefd11Sad 				rfc_sc->sc_curbuf->b_error = EIO;
883c049e276Sragge 				break;
884281464ebSragge 			}
885281464ebSragge 			disk_busy(&rf_sc->sc_disk);
886281464ebSragge 			if (rfc_sendcmd(rfc_sc, RX2CS_WSEC | RX2CS_IE
887281464ebSragge 			    | (rf_sc->sc_dnum == 0 ? 0 : RX2CS_US)
888281464ebSragge 			    | ((rf_sc->sc_state& RFS_DENS) == 0 ? 0 : RX2CS_DD),
889281464ebSragge 			    i % RX2_SECTORS + 1, i / RX2_SECTORS) < 0) {
890c049e276Sragge 				disk_unbusy(&rf_sc->sc_disk, 0, 0);
89166fefd11Sad 				rfc_sc->sc_curbuf->b_error = EIO;
892281464ebSragge 			}
893281464ebSragge 			break;
894281464ebSragge 		case RFS_RSEC:	/* Read Sector */
895281464ebSragge 			i = (rfc_sc->sc_curbuf->b_bcount - rfc_sc->sc_bytesleft
896281464ebSragge 			    + rfc_sc->sc_curbuf->b_blkno * DEV_BSIZE) /
897281464ebSragge 			    ((rf_sc->sc_state & RFS_DENS) == 0
898281464ebSragge 			    ? RX2_BYTE_SD : RX2_BYTE_DD);
899281464ebSragge 			if (i > RX2_TRACKS * RX2_SECTORS) {
90066fefd11Sad 				rfc_sc->sc_curbuf->b_error = EIO;
901c049e276Sragge 				break;
902281464ebSragge 			}
903281464ebSragge 			disk_busy(&rf_sc->sc_disk);
904281464ebSragge 			if (rfc_sendcmd(rfc_sc, RX2CS_RSEC | RX2CS_IE
905281464ebSragge 			    | (rf_sc->sc_dnum == 0 ? 0 : RX2CS_US)
906281464ebSragge 			    | ((rf_sc->sc_state& RFS_DENS) == 0 ? 0 : RX2CS_DD),
907281464ebSragge 			    i % RX2_SECTORS + 1, i / RX2_SECTORS) < 0) {
908c049e276Sragge 				disk_unbusy(&rf_sc->sc_disk, 0, 1);
90966fefd11Sad 				rfc_sc->sc_curbuf->b_error = EIO;
910281464ebSragge 			}
911281464ebSragge 			break;
912c049e276Sragge 		case RFS_NOTINIT: /* Device is not open */
913c049e276Sragge 		case RFS_PROBING: /* density detect / verify started */
914c049e276Sragge 		case RFS_IDLE:	/* controller is idle */
915281464ebSragge 		case RFS_SMD:	/* Set Media Density */
916281464ebSragge 		case RFS_RSTAT:	/* Read Status */
917281464ebSragge 		case RFS_WDDS:	/* Write Deleted Data Sector */
918281464ebSragge 		case RFS_REC:	/* Read Error Code */
919281464ebSragge 		default:
9206827de95Sjkunz 			panic("Impossible state in rfc_intr(2): 0x%x\n",
9216827de95Sjkunz 			    rf_sc->sc_state & RFS_CMDS);
922281464ebSragge 		}
923281464ebSragge 
92466fefd11Sad 		if (rfc_sc->sc_curbuf->b_error != 0) {
925c049e276Sragge 			/*
926f05e6f1aSwiz 			 * An error occurred while processing this buffer.
927c049e276Sragge 			 * Finish it and try to get a new buffer to process.
928c049e276Sragge 			 * Return if there are no buffers in the queues.
929c049e276Sragge 			 * This loops until the queues are empty or a new
930c049e276Sragge 			 * action was successfully scheduled.
931c049e276Sragge 			 */
932c049e276Sragge 			rfc_sc->sc_curbuf->b_resid = rfc_sc->sc_bytesleft;
933281464ebSragge 			rfc_sc->sc_curbuf->b_error = EIO;
934281464ebSragge 			biodone(rfc_sc->sc_curbuf);
935c049e276Sragge 			rf_sc = get_new_buf( rfc_sc);
936c049e276Sragge 			if (rf_sc == NULL)
937c049e276Sragge 				return;
938c049e276Sragge 			continue;
939281464ebSragge 		}
940bc2387e2Sdsl 		break;
941bc2387e2Sdsl 	}
942281464ebSragge 	return;
943281464ebSragge }
944281464ebSragge 
945281464ebSragge 
946281464ebSragge 
947281464ebSragge int
rfdump(dev_t dev,daddr_t blkno,void * va,size_t size)94853524e44Schristos rfdump(dev_t dev, daddr_t blkno, void *va, size_t size)
949281464ebSragge {
950281464ebSragge 
951281464ebSragge 	/* A 0.5MB floppy is much to small to take a system dump... */
952281464ebSragge 	return(ENXIO);
953281464ebSragge }
954281464ebSragge 
955281464ebSragge 
956281464ebSragge 
957281464ebSragge int
rfsize(dev_t dev)958281464ebSragge rfsize(dev_t dev)
959281464ebSragge {
960281464ebSragge 
961281464ebSragge 	return(-1);
962281464ebSragge }
963281464ebSragge 
964281464ebSragge 
965281464ebSragge 
966281464ebSragge int
rfopen(dev_t dev,int oflags,int devtype,struct lwp * l)96795e1ffb1Schristos rfopen(dev_t dev, int oflags, int devtype, struct lwp *l)
968281464ebSragge {
969281464ebSragge 	struct rf_softc *rf_sc;
970281464ebSragge 	struct rfc_softc *rfc_sc;
971281464ebSragge 	struct disklabel *dl;
972281464ebSragge 
973dfba8166Smatt 	if ((rf_sc = device_lookup_private(&rf_cd, DISKUNIT(dev))) == NULL)
974dfba8166Smatt 		return ENXIO;
975dfba8166Smatt 
976dfba8166Smatt 	rfc_sc = rf_sc->sc_rfc;
977281464ebSragge 	dl = rf_sc->sc_disk.dk_label;
978281464ebSragge 	switch (DISKPART(dev)) {
979281464ebSragge 		case 0:			/* Part. a is single density. */
9809876532dSwiz 			/* opening in single and double density is senseless */
981c049e276Sragge 			if ((rf_sc->sc_state & RFS_OPEN_B) != 0 )
982c049e276Sragge 				return(ENXIO);
983281464ebSragge 			rf_sc->sc_state &= ~RFS_DENS;
984281464ebSragge 			rf_sc->sc_state &= ~RFS_AD;
985c049e276Sragge 			rf_sc->sc_state |= RFS_OPEN_A;
986281464ebSragge 		break;
987281464ebSragge 		case 1:			/* Part. b is double density. */
988281464ebSragge 			/*
9899876532dSwiz 			 * Opening a single density only drive in double
990c049e276Sragge 			 * density or simultaneous opening in single and
9919876532dSwiz 			 * double density is senseless.
992281464ebSragge 			 */
993c049e276Sragge 			if (rfc_sc->type == 1
994c049e276Sragge 			    || (rf_sc->sc_state & RFS_OPEN_A) != 0 )
995281464ebSragge 				return(ENXIO);
996281464ebSragge 			rf_sc->sc_state |= RFS_DENS;
997281464ebSragge 			rf_sc->sc_state &= ~RFS_AD;
998c049e276Sragge 			rf_sc->sc_state |= RFS_OPEN_B;
999281464ebSragge 		break;
1000281464ebSragge 		case 2:			/* Part. c is auto density. */
1001281464ebSragge 			rf_sc->sc_state |= RFS_AD;
1002c049e276Sragge 			rf_sc->sc_state |= RFS_OPEN_C;
1003281464ebSragge 		break;
1004281464ebSragge 		default:
1005281464ebSragge 			return(ENXIO);
1006281464ebSragge 		break;
1007281464ebSragge 	}
1008281464ebSragge 	if ((rf_sc->sc_state & RFS_CMDS) == RFS_NOTINIT) {
1009281464ebSragge 		rfc_sc->sc_curchild = rf_sc->sc_dnum;
1010281464ebSragge 		/*
1011281464ebSragge 		 * Controller is idle and density is not detected.
1012281464ebSragge 		 * Start a density probe by issuing a read sector command
1013281464ebSragge 		 * and sleep until the density probe finished.
1014*38ad5e0eSandvar 		 * Due to this it is impossible to open unformatted media.
1015281464ebSragge 		 * As the RX02/02 is not able to format its own media,
1016*38ad5e0eSandvar 		 * media must be purchased preformatted. fsck DEC marketing!
1017281464ebSragge 		 */
1018281464ebSragge 		RFS_SETCMD(rf_sc->sc_state, RFS_PROBING);
1019281464ebSragge 		disk_busy(&rf_sc->sc_disk);
1020281464ebSragge 		if (rfc_sendcmd(rfc_sc, RX2CS_RSEC | RX2CS_IE
1021281464ebSragge 		    | (rf_sc->sc_dnum == 0 ? 0 : RX2CS_US)
1022281464ebSragge 		    | ((rf_sc->sc_state & RFS_DENS) == 0 ? 0 : RX2CS_DD),
1023281464ebSragge 		    1, 1) < 0) {
1024281464ebSragge 			rf_sc->sc_state = 0;
1025281464ebSragge 			return(ENXIO);
1026281464ebSragge 		}
1027281464ebSragge 		/* wait max. 2 sec for density probe to finish */
1028281464ebSragge 		if (tsleep(rf_sc, PRIBIO | PCATCH, "density probe", 2 * hz)
1029281464ebSragge 		    != 0 || (rf_sc->sc_state & RFS_CMDS) == RFS_NOTINIT) {
10309876532dSwiz 			/* timeout elapsed and / or something went wrong */
1031281464ebSragge 			rf_sc->sc_state = 0;
1032281464ebSragge 			return(ENXIO);
1033281464ebSragge 		}
1034281464ebSragge 	}
1035281464ebSragge 	/* disklabel. We use different fake geometries for SD and DD. */
1036281464ebSragge 	if ((rf_sc->sc_state & RFS_DENS) == 0) {
1037281464ebSragge 		dl->d_nsectors = 10;		/* sectors per track */
1038281464ebSragge 		dl->d_secpercyl = 10;		/* sectors per cylinder */
1039281464ebSragge 		dl->d_ncylinders = 50;		/* cylinders per unit */
1040281464ebSragge 		dl->d_secperunit = 501; /* sectors per unit */
1041281464ebSragge 		/* number of sectors in partition */
1042281464ebSragge 		dl->d_partitions[2].p_size = 500;
1043281464ebSragge 	} else {
1044281464ebSragge 		dl->d_nsectors = RX2_SECTORS / 2;  /* sectors per track */
1045281464ebSragge 		dl->d_secpercyl = RX2_SECTORS / 2; /* sectors per cylinder */
1046281464ebSragge 		dl->d_ncylinders = RX2_TRACKS;	   /* cylinders per unit */
1047281464ebSragge 		/* sectors per unit */
1048281464ebSragge 		dl->d_secperunit = RX2_SECTORS * RX2_TRACKS / 2;
1049281464ebSragge 		/* number of sectors in partition */
1050281464ebSragge 		dl->d_partitions[2].p_size = RX2_SECTORS * RX2_TRACKS / 2;
1051281464ebSragge 	}
1052281464ebSragge 	return(0);
1053281464ebSragge }
1054281464ebSragge 
1055281464ebSragge 
1056281464ebSragge 
1057281464ebSragge int
rfclose(dev_t dev,int fflag,int devtype,struct lwp * l)105895e1ffb1Schristos rfclose(dev_t dev, int fflag, int devtype, struct lwp *l)
1059281464ebSragge {
10606827de95Sjkunz 	struct rf_softc *rf_sc = device_lookup_private(&rf_cd, DISKUNIT(dev));
1061281464ebSragge 
1062c049e276Sragge 	if ((rf_sc->sc_state & 1 << (DISKPART(dev) + RFS_OPEN_SHIFT)) == 0)
10639876532dSwiz 		panic("rfclose: can not close non-open drive %s "
106423efc364Scegger 		    "partition %"PRIu32, device_xname(rf_sc->sc_dev), DISKPART(dev));
1065c049e276Sragge 	else
1066c049e276Sragge 		rf_sc->sc_state &= ~(1 << (DISKPART(dev) + RFS_OPEN_SHIFT));
1067c049e276Sragge 	if ((rf_sc->sc_state & RFS_OPEN_MASK) == 0)
1068281464ebSragge 		rf_sc->sc_state = 0;
1069281464ebSragge 	return(0);
1070281464ebSragge }
1071281464ebSragge 
1072281464ebSragge 
1073281464ebSragge 
1074281464ebSragge int
rfread(dev_t dev,struct uio * uio,int ioflag)1075281464ebSragge rfread(dev_t dev, struct uio *uio, int ioflag)
1076281464ebSragge {
1077281464ebSragge 
1078281464ebSragge 	return(physio(rfstrategy, NULL, dev, B_READ, minphys, uio));
1079281464ebSragge }
1080281464ebSragge 
1081281464ebSragge 
1082281464ebSragge 
1083281464ebSragge int
rfwrite(dev_t dev,struct uio * uio,int ioflag)1084281464ebSragge rfwrite(dev_t dev, struct uio *uio, int ioflag)
1085281464ebSragge {
1086281464ebSragge 
1087281464ebSragge 	return(physio(rfstrategy, NULL, dev, B_WRITE, minphys, uio));
1088281464ebSragge }
1089281464ebSragge 
1090281464ebSragge 
1091281464ebSragge 
1092281464ebSragge int
rfioctl(dev_t dev,u_long cmd,void * data,int fflag,struct lwp * l)109353524e44Schristos rfioctl(dev_t dev, u_long cmd, void *data, int fflag, struct lwp *l)
1094281464ebSragge {
10956827de95Sjkunz 	struct rf_softc *rf_sc = device_lookup_private(&rf_cd, DISKUNIT(dev));
1096c60db2e9Schristos 	int error;
1097281464ebSragge 
10989876532dSwiz 	/* We are going to operate on a non-open dev? PANIC! */
1099c049e276Sragge 	if ((rf_sc->sc_state & 1 << (DISKPART(dev) + RFS_OPEN_SHIFT)) == 0)
1100c049e276Sragge 		panic("rfioctl: can not operate on non-open drive %s "
110123efc364Scegger 		    "partition %"PRIu32, device_xname(rf_sc->sc_dev), DISKPART(dev));
1102c60db2e9Schristos 	error = disk_ioctl(&rf_sc->sc_disk, dev, cmd, data, fflag, l);
1103c60db2e9Schristos 	if (error != EPASSTHROUGH)
1104c60db2e9Schristos 		return error;
1105c60db2e9Schristos 
1106281464ebSragge 	switch (cmd) {
11078d10f962Schristos 	/* get and set disklabel; DIOCGPARTINFO used internally */
1108281464ebSragge 	case DIOCSDINFO: /* set */
1109281464ebSragge 		return(0);
1110281464ebSragge 	case DIOCWDINFO: /* set, update disk */
1111281464ebSragge 		return(0);
1112281464ebSragge 	/* do format operation, read or write */
1113281464ebSragge 	case DIOCRFORMAT:
1114281464ebSragge 	break;
1115281464ebSragge 	case DIOCWFORMAT:
1116281464ebSragge 	break;
1117281464ebSragge 
1118281464ebSragge 	case DIOCSSTEP: /* set step rate */
1119281464ebSragge 	break;
1120281464ebSragge 	case DIOCSRETRIES: /* set # of retries */
1121281464ebSragge 	break;
1122281464ebSragge 	case DIOCKLABEL: /* keep/drop label on close? */
1123281464ebSragge 	break;
1124281464ebSragge 	case DIOCWLABEL: /* write en/disable label */
1125281464ebSragge 	break;
1126281464ebSragge 
1127281464ebSragge /*	case DIOCSBAD: / * set kernel dkbad */
1128281464ebSragge 	break; /* */
1129281464ebSragge 	case DIOCEJECT: /* eject removable disk */
1130281464ebSragge 	break;
1131281464ebSragge 	case ODIOCEJECT: /* eject removable disk */
1132281464ebSragge 	break;
1133281464ebSragge 	case DIOCLOCK: /* lock/unlock pack */
1134281464ebSragge 	break;
1135281464ebSragge 
1136281464ebSragge 	/* get default label, clear label */
1137281464ebSragge 	case DIOCGDEFLABEL:
1138281464ebSragge 	break;
1139281464ebSragge 	case DIOCCLRLABEL:
1140281464ebSragge 	break;
1141281464ebSragge 	default:
1142281464ebSragge 		return(ENOTTY);
1143281464ebSragge 	}
1144281464ebSragge 
1145281464ebSragge 	return(ENOTTY);
1146281464ebSragge }
1147