xref: /netbsd-src/sys/dev/qbus/rf.c (revision d710132b4b8ce7f7cccaaf660cb16aa16b4077a0)
1 /*	$NetBSD: rf.c,v 1.2 2003/05/03 18:11:38 wiz Exp $	*/
2 /*
3  * Copyright (c) 2002 Jochen Kunz.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of Jochen Kunz may not be used to endorse or promote
15  *    products derived from this software without specific prior
16  *    written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY JOCHEN KUNZ
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL JOCHEN KUNZ
22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /*
32 TODO:
33 - Better LBN bound checking, block padding for SD disks.
34 - Formating / "Set Density"
35 - Better error handling / detaild error reason reportnig.
36 */
37 
38 /* autoconfig stuff */
39 #include <sys/param.h>
40 #include <sys/device.h>
41 #include <sys/conf.h>
42 #include "locators.h"
43 #include "ioconf.h"
44 
45 /* bus_space / bus_dma */
46 #include <machine/bus.h>
47 
48 /* UniBus / QBus specific stuff */
49 #include <dev/qbus/ubavar.h>
50 
51 /* disk interface */
52 #include <sys/types.h>
53 #include <sys/disklabel.h>
54 #include <sys/disk.h>
55 
56 /* general system data and functions */
57 #include <sys/systm.h>
58 #include <sys/ioctl.h>
59 #include <sys/ioccom.h>
60 
61 /* physio / buffer handling */
62 #include <sys/buf.h>
63 
64 /* tsleep / sleep / wakeup */
65 #include <sys/proc.h>
66 /* hz for above */
67 #include <sys/kernel.h>
68 
69 /* bitdefinitions for RX211 */
70 #include <dev/qbus/rfreg.h>
71 
72 
73 #define	RFS_DENS	0x0001		/* single or double density */
74 #define	RFS_AD		0x0002		/* density auto detect */
75 #define	RFS_NOTINIT	0x0000		/* not initialized */
76 #define	RFS_PROBING	0x0010		/* density detect / verify started */
77 #define	RFS_FBUF	0x0020		/* Fill Buffer */
78 #define	RFS_EBUF	0x0030		/* Empty Buffer */
79 #define	RFS_WSEC	0x0040		/* Write Sector */
80 #define	RFS_RSEC	0x0050		/* Read Sector */
81 #define	RFS_SMD		0x0060		/* Set Media Density */
82 #define	RFS_RSTAT	0x0070		/* Read Status */
83 #define	RFS_WDDS	0x0080		/* Write Deleted Data Sector */
84 #define	RFS_REC		0x0090		/* Read Error Code */
85 #define	RFS_IDLE	0x00a0		/* controller is idle */
86 #define	RFS_CMDS	0x00f0		/* command mask */
87 #define	RFS_SETCMD(rf, state)	((rf) = ((rf) & ~RFS_CMDS) | (state))
88 
89 
90 
91 /* autoconfig stuff */
92 static int rfc_match(struct device *, struct cfdata *, void *);
93 static void rfc_attach(struct device *, struct device *, void *);
94 static int rf_match(struct device *, struct cfdata *, void *);
95 static void rf_attach(struct device *, struct device *, void *);
96 static int rf_print(void *, const char *);
97 
98 /* device interfce functions / interface to disk(9) */
99 dev_type_open(rfopen);
100 dev_type_close(rfclose);
101 dev_type_read(rfread);
102 dev_type_write(rfwrite);
103 dev_type_ioctl(rfioctl);
104 dev_type_strategy(rfstrategy);
105 dev_type_dump(rfdump);
106 dev_type_size(rfsize);
107 
108 
109 /* Entries in block and character major device number switch table. */
110 const struct bdevsw rf_bdevsw = {
111 	rfopen,
112 	rfclose,
113 	rfstrategy,
114 	rfioctl,
115 	rfdump,
116 	rfsize,
117 	D_DISK
118 };
119 
120 const struct cdevsw rf_cdevsw = {
121 	rfopen,
122 	rfclose,
123 	rfread,
124 	rfwrite,
125 	rfioctl,
126 	nostop,
127 	notty,
128 	nopoll,
129 	nommap,
130 	nokqfilter,
131 	D_DISK
132 };
133 
134 
135 
136 struct rfc_softc {
137 	struct device sc_dev;		/* common device data */
138 	struct device *sc_childs[2];	/* child devices */
139 	struct evcnt sc_intr_count;	/* Interrupt counter for statistics */
140 	struct buf *sc_curbuf;		/* buf that is currently in work */
141 	bus_space_tag_t sc_iot;		/* bus_space IO tag */
142 	bus_space_handle_t sc_ioh;	/* bus_space IO handle */
143 	bus_dma_tag_t sc_dmat;		/* bus_dma DMA tag */
144 	bus_dmamap_t sc_dmam;		/* bus_dma DMA map */
145 	caddr_t sc_bufidx;		/* current position in buffer data */
146 	int sc_curchild;		/* child whos bufq is in work */
147 	int sc_bytesleft;		/* bytes left to transfer */
148 	u_int8_t type;			/* controller type, 1 or 2 */
149 };
150 
151 
152 
153 CFATTACH_DECL(
154 	rfc,
155 	sizeof(struct rfc_softc),
156 	rfc_match,
157 	rfc_attach,
158 	NULL,
159     	NULL
160 );
161 
162 
163 
164 struct rf_softc {
165 	struct device sc_dev;		/* common device data */
166 	struct disk sc_disk;		/* common disk device data */
167 	struct bufq_state sc_bufq;	/* queue of pending transfers */
168 	int sc_state;			/* state of drive */
169 	int sc_open;			/* simultaneous opens */
170 	u_int8_t sc_dnum;		/* drive number, 0 or 1 */
171 };
172 
173 
174 
175 CFATTACH_DECL(
176 	rf,
177 	sizeof(struct rf_softc),
178 	rf_match,
179 	rf_attach,
180 	NULL,
181 	NULL
182 );
183 
184 
185 
186 struct rfc_attach_args {
187 	u_int8_t type;		/* controller type, 1 or 2 */
188 	u_int8_t dnum;		/* drive number, 0 or 1 */
189 };
190 
191 
192 
193 struct dkdriver rfdkdriver = {
194 	rfstrategy
195 };
196 
197 
198 
199 /* helper functions */
200 int rfc_sendcmd(struct rfc_softc *, int, int, int);
201 static void rfc_intr(void *);
202 
203 
204 
205 /*
206  * Issue a reset command to the controller and look for the bits in
207  * RX2CS and RX2ES.
208  * RX2CS_RX02 and / or RX2CS_DD can be set,
209  * RX2ES has to be set, all other bits must be 0
210  */
211 int
212 rfc_match(struct device *parent, struct cfdata *match, void *aux)
213 {
214 	struct uba_attach_args *ua = aux;
215 	int i;
216 
217 	/* Issue reset command. */
218 	bus_space_write_2(ua->ua_iot, ua->ua_ioh, RX2CS, RX2CS_INIT);
219 	/* Wait for the controller to become ready, that is when
220 	 * RX2CS_DONE, RX2ES_RDY and RX2ES_ID are set. */
221 	for (i = 0 ; i < 20 ; i++) {
222 		if ((bus_space_read_2(ua->ua_iot, ua->ua_ioh, RX2CS)
223 		    & RX2CS_DONE) != 0
224 		    && (bus_space_read_2(ua->ua_iot, ua->ua_ioh, RX2ES)
225 		    & (RX2ES_RDY | RX2ES_ID)) != 0)
226 			break;
227 		DELAY(100000);	/* wait 100ms */
228 	}
229 	/*
230 	 * Give up if the timeout has elapsed
231 	 * and the controller is not ready.
232 	 */
233 	if (i >= 20)
234 		return(0);
235 	/*
236 	 * Issue a Read Status command with interrupt enabled.
237 	 * The uba(4) driver wants to catch the interrupt to get the
238 	 * interrupt vector and level of the device
239 	 */
240 	bus_space_write_2(ua->ua_iot, ua->ua_ioh, RX2CS,
241 	    RX2CS_RSTAT | RX2CS_IE);
242 	/*
243 	 * Wait for command to finish, ignore errors and
244 	 * abort if the controller does not respond within the timeout
245 	 */
246 	for (i = 0 ; i < 20 ; i++) {
247 		if ((bus_space_read_2(ua->ua_iot, ua->ua_ioh, RX2CS)
248 		    & (RX2CS_DONE | RX2CS_IE)) != 0
249 		    && (bus_space_read_2(ua->ua_iot, ua->ua_ioh, RX2ES)
250 		    & RX2ES_RDY) != 0 )
251 			return(1);
252 		DELAY(100000);	/* wait 100ms */
253 	}
254 	return(0);
255 }
256 
257 
258 
259 /* #define RX02_PROBE 1 */
260 #ifdef RX02_PROBE
261 /*
262  * Probe the density of an inserted floppy disk.
263  * This is done by reading a sector from disk.
264  * Return -1 on error, 0 on SD and 1 on DD.
265  */
266 int rfcprobedens(struct rfc_softc *, int);
267 int
268 rfcprobedens(struct rfc_softc *rfc_sc, int dnum)
269 {
270 	int dens_flag;
271 	int i;
272 
273 	dens_flag = 0;
274 	do {
275 		bus_space_write_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS,
276 		    RX2CS_RSEC | (dens_flag == 0 ? 0 : RX2CS_DD)
277 		    | (dnum == 0 ? 0 : RX2CS_US));
278 		/*
279 		 * Transfer request set?
280 		 * Wait 50us, the controller needs this time to setle
281 		 */
282 		DELAY(50);
283 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
284 		    & RX2CS_TR) == 0) {
285 			printf("%s: did not respond to Read Sector CMD(1)\n",
286 			    rfc_sc->sc_dev.dv_xname);
287 			return(-1);
288 		}
289 		bus_space_write_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2SA, 1);
290 		/* Wait 50us, the controller needs this time to setle */
291 		DELAY(50);
292 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
293 		    & RX2CS_TR) == 0) {
294 			printf("%s: did not respond to Read Sector CMD(2)\n",
295 			    rfc_sc->sc_dev.dv_xname);
296 			return(-1);
297 		}
298 		bus_space_write_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2TA, 1);
299 		/* Wait for the command to finish */
300 		for (i = 0 ; i < 200 ; i++) {
301 			if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh,
302 			    RX2CS) & RX2CS_DONE) != 0)
303 				break;
304 			DELAY(10000);	/* wait 10ms */
305 		}
306 		if (i >= 200) {
307 			printf("%s: did not respond to Read Sector CMD(3)\n",
308 			    rfc_sc->sc_dev.dv_xname);
309 			return(-1);
310 		}
311 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
312 		    & RX2CS_ERR) == 0)
313 			return(dens_flag);
314 	} while (rfc_sc->type == 2 && dens_flag++ == 0);
315 	return(-1);
316 }
317 #endif /* RX02_PROBE */
318 
319 
320 
321 void
322 rfc_attach(struct device *parent, struct device *self, void *aux)
323 {
324 	struct rfc_softc *rfc_sc = (struct rfc_softc *)self;
325 	struct uba_attach_args *ua = aux;
326 	struct rfc_attach_args rfc_aa;
327 	int i;
328 
329 	rfc_sc->sc_iot = ua->ua_iot;
330 	rfc_sc->sc_ioh = ua->ua_ioh;
331 	rfc_sc->sc_dmat = ua->ua_dmat;
332 	rfc_sc->sc_curbuf = NULL;
333 	/* Tell the QBus busdriver about our interrupt handler. */
334 	uba_intr_establish(ua->ua_icookie, ua->ua_cvec, rfc_intr, rfc_sc,
335 	    &rfc_sc->sc_intr_count);
336 	/* Attach to the interrupt counter, see evcnt(9) */
337 	evcnt_attach_dynamic(&rfc_sc->sc_intr_count, EVCNT_TYPE_INTR,
338 	    ua->ua_evcnt, rfc_sc->sc_dev.dv_xname, "intr");
339 	/* get a bus_dma(9) handle */
340 	i = bus_dmamap_create(rfc_sc->sc_dmat, RX2_BYTE_DD, 1, RX2_BYTE_DD, 0,
341 	    BUS_DMA_ALLOCNOW, &rfc_sc->sc_dmam);
342 	if (i != 0) {
343 		printf("rfc_attach: Error creating bus DMA map: %d\n", i);
344 		return;
345 	}
346 
347 	/* Issue reset command. */
348 	bus_space_write_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS, RX2CS_INIT);
349 	/*
350 	 * Wait for the controller to become ready, that is when
351 	 * RX2CS_DONE, RX2ES_RDY and RX2ES_ID are set.
352 	 */
353 	for (i = 0 ; i < 20 ; i++) {
354 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
355 		    & RX2CS_DONE) != 0
356 		    && (bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2ES)
357 		    & (RX2ES_RDY | RX2ES_ID)) != 0)
358 			break;
359 		DELAY(100000);	/* wait 100ms */
360 	}
361 	/*
362 	 * Give up if the timeout has elapsed
363 	 * and the controller is not ready.
364 	 */
365 	if (i >= 20) {
366 		printf(": did not respond to INIT CMD\n");
367 		return;
368 	}
369 	/* Is ths a RX01 or a RX02? */
370 	if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
371 	    & RX2CS_RX02) != 0) {
372 		rfc_sc->type = 2;
373 		rfc_aa.type = 2;
374 	} else {
375 		rfc_sc->type = 1;
376 		rfc_aa.type = 1;
377 	}
378 	printf(": RX0%d\n", rfc_sc->type);
379 
380 #ifndef RX02_PROBE
381 	/*
382 	 * Bouth disk drievs and the controller are one physical unit.
383 	 * If we found the controller, there will be bouth disk drievs.
384 	 * So attach them.
385 	 */
386 	rfc_aa.dnum = 0;
387 	rfc_sc->sc_childs[0] = config_found(&rfc_sc->sc_dev, &rfc_aa,rf_print);
388 	rfc_aa.dnum = 1;
389 	rfc_sc->sc_childs[1] = config_found(&rfc_sc->sc_dev, &rfc_aa,rf_print);
390 #else /* RX02_PROBE */
391 	/*
392 	 * There are clones of the DEC RX system with standard shugart
393 	 * interface. In this case we can not be sure that there are
394 	 * bouth disk drievs. So we want to do a detection of attached
395 	 * drives. This is done by reading a sector from disk. This means
396 	 * that there must be a formated disk in the drive at boot time.
397 	 * This is bad, but I did not find an other way to detect the
398 	 * (non)existence of a floppy drive.
399 	 */
400 	if (rfcprobedens(rfc_sc, 0) >= 0) {
401 		rfc_aa.dnum = 0;
402 		rfc_sc->sc_childs[0] = config_found(&rfc_sc->sc_dev, &rfc_aa,
403 		    rf_print);
404 	} else
405 		rfc_sc->sc_childs[0] = NULL;
406 	if (rfcprobedens(rfc_sc, 1) >= 0) {
407 		rfc_aa.dnum = 1;
408 		rfc_sc->sc_childs[1] = config_found(&rfc_sc->sc_dev, &rfc_aa,
409 		    rf_print);
410 	} else
411 		rfc_sc->sc_childs[1] = NULL;
412 #endif /* RX02_PROBE */
413 	return;
414 }
415 
416 
417 
418 int
419 rf_match(struct device *parent, struct cfdata *match, void *aux)
420 {
421 	struct rfc_attach_args *rfc_aa = aux;
422 
423 	/*
424 	 * Only attach if the locator is wildcarded or
425 	 * if the specified locator addresses the current device.
426 	 */
427 	if (match->cf_loc[RFCCF_DRIVE] == RFCCF_DRIVE_DEFAULT ||
428 	    match->cf_loc[RFCCF_DRIVE] == rfc_aa->dnum)
429 		return(1);
430 	return(0);
431 }
432 
433 
434 
435 void
436 rf_attach(struct device *parent, struct device *self, void *aux)
437 {
438 	struct rf_softc *rf_sc = (struct rf_softc *)self;
439 	struct rfc_attach_args *rfc_aa = (struct rfc_attach_args *)aux;
440 	struct rfc_softc *rfc_sc;
441 	struct disklabel *dl;
442 
443 	rfc_sc = (struct rfc_softc *)rf_sc->sc_dev.dv_parent;
444 	rf_sc->sc_dnum = rfc_aa->dnum;
445 	rf_sc->sc_state = 0;
446 	rf_sc->sc_open = 0;
447 	rf_sc->sc_disk.dk_name = rf_sc->sc_dev.dv_xname;
448 	rf_sc->sc_disk.dk_driver = &rfdkdriver;
449 	disk_attach(&rf_sc->sc_disk);
450 	dl = rf_sc->sc_disk.dk_label;
451 	dl->d_type = DTYPE_FLOPPY;		/* drive type */
452 	dl->d_magic = DISKMAGIC;		/* the magic number */
453 	dl->d_magic2 = DISKMAGIC;
454 	dl->d_typename[0] = 'R';
455 	dl->d_typename[1] = 'X';
456 	dl->d_typename[2] = '0';
457 	dl->d_typename[3] = rfc_sc->type == 1 ? '1' : '2';	/* type name */
458 	dl->d_typename[4] = '\0';
459 	dl->d_secsize = DEV_BSIZE;		/* bytes per sector */
460 	/*
461 	 * Fill in some values to have a initialized data structure. Some
462 	 * values will be reset by rfopen() depending on the actual density.
463 	 */
464 	dl->d_nsectors = RX2_SECTORS;		/* sectors per track */
465 	dl->d_ntracks = 1;								/* tracks per cylinder */
466 	dl->d_ncylinders = RX2_TRACKS;		/* cylinders per unit */
467 	dl->d_secpercyl = RX2_SECTORS;		/* sectors per cylinder */
468 	dl->d_secperunit = RX2_SECTORS * RX2_TRACKS;	/* sectors per unit */
469 	dl->d_rpm = 360;			/* rotational speed */
470 	dl->d_interleave = 1;			/* hardware sector interleave */
471 	/* number of partitions in following */
472 	dl->d_npartitions = MAXPARTITIONS;
473 	dl->d_bbsize = 0;		/* size of boot area at sn0, bytes */
474 	dl->d_sbsize = 0;		/* max size of fs superblock, bytes */
475 	/* number of sectors in partition */
476 	dl->d_partitions[0].p_size = 501;
477 	dl->d_partitions[0].p_offset = 0;	/* starting sector */
478 	dl->d_partitions[0].p_fsize = 0;	/* fs basic fragment size */
479 	dl->d_partitions[0].p_fstype = 0;	/* fs type */
480 	dl->d_partitions[0].p_frag = 0;		/* fs fragments per block */
481 	dl->d_partitions[1].p_size = RX2_SECTORS * RX2_TRACKS / 2;
482 	dl->d_partitions[1].p_offset = 0;	/* starting sector */
483 	dl->d_partitions[1].p_fsize = 0;	/* fs basic fragment size */
484 	dl->d_partitions[1].p_fstype = 0;	/* fs type */
485 	dl->d_partitions[1].p_frag = 0;		/* fs fragments per block */
486 	dl->d_partitions[2].p_size = RX2_SECTORS * RX2_TRACKS;
487 	dl->d_partitions[2].p_offset = 0;	/* starting sector */
488 	dl->d_partitions[2].p_fsize = 0;	/* fs basic fragment size */
489 	dl->d_partitions[2].p_fstype = 0;	/* fs type */
490 	dl->d_partitions[2].p_frag = 0;		/* fs fragments per block */
491 	bufq_alloc(&rf_sc->sc_bufq, BUFQ_DISKSORT | BUFQ_SORT_CYLINDER);
492 	printf("\n");
493 	return;
494 }
495 
496 
497 
498 int
499 rf_print(void *aux, const char *name)
500 {
501 	struct rfc_attach_args *rfc_aa = aux;
502 
503 	if (name != NULL)
504 		aprint_normal("RX0%d at %s", rfc_aa->type, name);
505 	aprint_normal(" drive %d", rfc_aa->dnum);
506 	return(UNCONF);
507 }
508 
509 
510 
511 /* Send a command to the controller */
512 int
513 rfc_sendcmd(struct rfc_softc *rfc_sc, int cmd, int data1, int data2)
514 {
515 
516 	/* Write command to CSR. */
517 	bus_space_write_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS, cmd);
518 	/* Wait 50us, the controller needs this time to setle. */
519 	DELAY(50);
520 	/* Write parameter 1 to DBR */
521 	if ((cmd & RX2CS_FC) != RX2CS_RSTAT) {
522 		/* Transfer request set? */
523 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
524 		    & RX2CS_TR) == 0) {
525 			printf("%s: did not respond to CMD %x (1)\n",
526 			    rfc_sc->sc_dev.dv_xname, cmd);
527 			return(-1);
528 		}
529 		bus_space_write_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2DB,
530 		    data1);
531 	}
532 	/* Write parameter 2 to DBR */
533 	if ((cmd & RX2CS_FC) <= RX2CS_RSEC || (cmd & RX2CS_FC) == RX2CS_WDDS) {
534 		/* Wait 50us, the controller needs this time to setle. */
535 		DELAY(50);
536 		/* Transfer request set? */
537 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
538 		    & RX2CS_TR) == 0) {
539 			printf("%s: did not respond to CMD %x (2)\n",
540 			    rfc_sc->sc_dev.dv_xname, cmd);
541 			return(-1);
542 		}
543 		bus_space_write_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2DB,
544 		    data2);
545 	}
546 	return(1);
547 }
548 
549 
550 
551 void
552 rfstrategy(struct buf *buf)
553 {
554 	struct rf_softc *rf_sc;
555 	struct rfc_softc *rfc_sc;
556 	int i;
557 
558 	i = DISKUNIT(buf->b_dev);
559 	if (i >= rf_cd.cd_ndevs || (rf_sc = rf_cd.cd_devs[i]) == NULL) {
560 		buf->b_flags |= B_ERROR;
561 		buf->b_error = ENXIO;
562 		biodone(buf);
563 		return;
564 	}
565 	rfc_sc = (struct rfc_softc *)rf_sc->sc_dev.dv_parent;
566 	/* We are going to operate on a non open dev? PANIC! */
567 	if (rf_sc->sc_open == 0)
568 		panic("rfstrategy: can not operate on non-open drive %s (1)",
569 		    rf_sc->sc_dev.dv_xname);
570 	if (buf->b_bcount == 0) {
571 		biodone(buf);
572 		return;
573 	}
574 	/*
575 	 * BUFQ_PUT() operates on b_rawblkno. rfstrategy() gets
576 	 * only b_blkno that is partition relative. As a floppy does not
577 	 * have partitions b_rawblkno == b_blkno.
578 	 */
579 	buf->b_rawblkno = buf->b_blkno;
580 	/*
581 	 * from sys/kern/subr_disk.c:
582 	 * Seek sort for disks.  We depend on the driver which calls us using
583 	 * b_resid as the current cylinder number.
584 	 */
585 	i = splbio();
586 	if (rfc_sc->sc_curbuf == NULL) {
587 		rfc_sc->sc_curchild = rf_sc->sc_dnum;
588 		rfc_sc->sc_curbuf = buf;
589 		rfc_sc->sc_bufidx = buf->b_un.b_addr;
590 		rfc_sc->sc_bytesleft = buf->b_bcount;
591 		rfc_intr(rfc_sc);
592 	} else {
593 		buf->b_resid = buf->b_blkno / RX2_SECTORS;
594 		BUFQ_PUT(&rf_sc->sc_bufq, buf);
595 		rfc_sc->sc_curbuf->b_resid = 0;
596 	}
597 	splx(i);
598 	return;
599 }
600 
601 
602 
603 void
604 rfc_intr(void *intarg)
605 {
606 	struct rfc_softc *rfc_sc = intarg;
607 	struct rf_softc *rf_sc;
608 	struct rf_softc *other_drive;
609 	int i;
610 
611 	rf_sc = (struct rf_softc *)rfc_sc->sc_childs[rfc_sc->sc_curchild];
612 	/*
613 	 * First clean up from previous command...
614 	 */
615 	switch (rf_sc->sc_state & RFS_CMDS) {
616 	case RFS_PROBING:	/* density detect / verify started */
617 		disk_unbusy(&rf_sc->sc_disk, 0, 1);
618 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
619 		    & RX2CS_ERR) == 0) {
620 			RFS_SETCMD(rf_sc->sc_state, RFS_IDLE);
621 			wakeup(rf_sc);
622 		} else {
623 			if (rfc_sc->type == 2
624 			    && (rf_sc->sc_state & RFS_DENS) == 0
625 			    && (rf_sc->sc_state & RFS_AD) != 0) {
626 				/* retry at DD */
627 				rf_sc->sc_state |= RFS_DENS;
628 				disk_busy(&rf_sc->sc_disk);
629 				if (rfc_sendcmd(rfc_sc, RX2CS_RSEC | RX2CS_IE
630 				    | RX2CS_DD | (rf_sc->sc_dnum == 0
631 				    ? 0 : RX2CS_US), 1, 1) < 0) {
632 					rfc_sc->sc_curbuf->b_flags |= B_ERROR;
633 					RFS_SETCMD(rf_sc->sc_state,
634 					    RFS_NOTINIT);
635 					wakeup(rf_sc);
636 				}
637 			} else {
638 				printf("%s: density error.\n",
639 				    rf_sc->sc_dev.dv_xname);
640 				rfc_sc->sc_curbuf->b_flags |= B_ERROR;
641 				RFS_SETCMD(rf_sc->sc_state, RFS_NOTINIT);
642 				wakeup(rf_sc);
643 			}
644 		}
645 		return;
646 	case RFS_IDLE:	/* controller is idle */
647 		if (rfc_sc->sc_curbuf->b_bcount
648 		    % ((rf_sc->sc_state & RFS_DENS) == 0
649 		    ? RX2_BYTE_SD : RX2_BYTE_DD) != 0) {
650 			/*
651 			 * can only handle blocks that are a multiple of the
652 			 * physical block size
653 			 */
654 			rfc_sc->sc_curbuf->b_flags |= B_ERROR;
655 			break;
656 		}
657 		RFS_SETCMD(rf_sc->sc_state, (rfc_sc->sc_curbuf->b_flags
658 		    & B_READ) != 0 ? RFS_RSEC : RFS_FBUF);
659 		break;
660 	case RFS_RSEC:	/* Read Sector */
661 		disk_unbusy(&rf_sc->sc_disk, 0, 1);
662 		/* check for errors */
663 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
664 		    & RX2CS_ERR) != 0) {
665 			/* should do more verbose error reporting */
666 			printf("rfc_intr: Error while reading secotr: %x\n",
667 			    bus_space_read_2(rfc_sc->sc_iot,
668 			    rfc_sc->sc_ioh, RX2ES) );
669 			rfc_sc->sc_curbuf->b_flags |= B_ERROR;
670 			break;
671 		}
672 		RFS_SETCMD(rf_sc->sc_state, RFS_EBUF);
673 		break;
674 	case RFS_WSEC:	/* Write Sector */
675 		i = (rf_sc->sc_state & RFS_DENS) == 0
676 			? RX2_BYTE_SD : RX2_BYTE_DD;
677 		disk_unbusy(&rf_sc->sc_disk, i, 0);
678 		/* check for errors */
679 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
680 		    & RX2CS_ERR) != 0) {
681 			/* should do more verbose error reporting */
682 			printf("rfc_intr: Error while writing secotr: %x\n",
683 			    bus_space_read_2(rfc_sc->sc_iot,
684 			    rfc_sc->sc_ioh, RX2ES) );
685 			rfc_sc->sc_curbuf->b_flags |= B_ERROR;
686 			break;
687 		}
688 		if (rfc_sc->sc_bytesleft > i) {
689 			rfc_sc->sc_bytesleft -= i;
690 			rfc_sc->sc_bufidx += i;
691 		} else {
692 			biodone(rfc_sc->sc_curbuf);
693 			rfc_sc->sc_curbuf = BUFQ_GET(&rf_sc->sc_bufq);
694 			if (rfc_sc->sc_curbuf != NULL) {
695 				rfc_sc->sc_bufidx =
696 				    rfc_sc->sc_curbuf->b_un.b_addr;
697 				rfc_sc->sc_bytesleft =
698 				    rfc_sc->sc_curbuf->b_bcount;
699 			} else {
700 				RFS_SETCMD(rf_sc->sc_state, RFS_IDLE);
701 				/*
702 				 * Switch to the other drive if there where
703 				 * buffers queued while we where working on
704 				 * the buffer queue of this drive
705 				 */
706 				other_drive = (struct rf_softc *)
707 				    rfc_sc->sc_childs[
708 				    rfc_sc->sc_curchild == 0 ? 1 : 0];
709 				if (other_drive != NULL && BUFQ_PEEK(
710 					&other_drive->sc_bufq) != NULL) {
711 					rfc_sc->sc_curchild =
712 					    rfc_sc->sc_curchild == 0 ? 1 : 0;
713 					rf_sc = other_drive;
714 					rfc_sc->sc_curbuf =
715 					    BUFQ_GET(&rf_sc->sc_bufq);
716 					rfc_sc->sc_bufidx =
717 					    rfc_sc->sc_curbuf->b_un.b_addr;
718 					rfc_sc->sc_bytesleft =
719 					    rfc_sc->sc_curbuf->b_bcount;
720 				} else
721 					return;
722 			}
723 		}
724 		RFS_SETCMD(rf_sc->sc_state,
725 		    (rfc_sc->sc_curbuf->b_flags & B_READ) != 0
726 		    ? RFS_RSEC : RFS_FBUF);
727 		break;
728 	case RFS_FBUF:	/* Fill Buffer */
729 		disk_unbusy(&rf_sc->sc_disk, 0, 0);
730 		/* check for errors */
731 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
732 		    & RX2CS_ERR) != 0) {
733 			/* should do more verbose error reporting */
734 			printf("rfc_intr: Error while DMA: %x\n",
735 			    bus_space_read_2(rfc_sc->sc_iot,
736 			    rfc_sc->sc_ioh, RX2ES));
737 			rfc_sc->sc_curbuf->b_flags |= B_ERROR;
738 		}
739 		bus_dmamap_unload(rfc_sc->sc_dmat, rfc_sc->sc_dmam);
740 		RFS_SETCMD(rf_sc->sc_state, RFS_WSEC);
741 		break;
742 	case RFS_EBUF:	/* Empty Buffer */
743 		i = (rf_sc->sc_state & RFS_DENS) == 0
744 		    ? RX2_BYTE_SD : RX2_BYTE_DD;
745 		disk_unbusy(&rf_sc->sc_disk, i, 1);
746 		/* check for errors */
747 		if ((bus_space_read_2(rfc_sc->sc_iot, rfc_sc->sc_ioh, RX2CS)
748 			& RX2CS_ERR) != 0) {
749 			/* should do more verbose error reporting */
750 			printf("rfc_intr: Error while DMA: %x\n",
751 			    bus_space_read_2(rfc_sc->sc_iot,
752 			    rfc_sc->sc_ioh, RX2ES));
753 			rfc_sc->sc_curbuf->b_flags |= B_ERROR;
754 		}
755 		bus_dmamap_unload(rfc_sc->sc_dmat, rfc_sc->sc_dmam);
756 		if (rfc_sc->sc_bytesleft > i) {
757 			rfc_sc->sc_bytesleft -= i;
758 			rfc_sc->sc_bufidx += i;
759 		} else {
760 			biodone(rfc_sc->sc_curbuf);
761 			rfc_sc->sc_curbuf = BUFQ_GET(&rf_sc->sc_bufq);
762 			if (rfc_sc->sc_curbuf != NULL) {
763 				rfc_sc->sc_bufidx =
764 				    rfc_sc->sc_curbuf->b_un.b_addr;
765 				rfc_sc->sc_bytesleft =
766 				    rfc_sc->sc_curbuf->b_bcount;
767 			} else {
768 				RFS_SETCMD(rf_sc->sc_state, RFS_IDLE);
769 				/*
770 				 * Switch to the other drive if there where
771 				 * buffers queued while we where working on
772 				 * the buffer queue of this drive
773 				 */
774 				other_drive = (struct rf_softc *)
775 				    rfc_sc->sc_childs[
776 				    rfc_sc->sc_curchild == 0 ? 1 : 0];
777 				if (other_drive != NULL && BUFQ_PEEK(
778 					&other_drive->sc_bufq) != NULL) {
779 					rfc_sc->sc_curchild =
780 					    rfc_sc->sc_curchild == 0 ? 1 : 0;
781 					rf_sc = other_drive;
782 					rfc_sc->sc_curbuf =
783 					    BUFQ_GET(&rf_sc->sc_bufq);
784 					rfc_sc->sc_bufidx =
785 					    rfc_sc->sc_curbuf->b_un.b_addr;
786 					rfc_sc->sc_bytesleft =
787 					    rfc_sc->sc_curbuf->b_bcount;
788 				} else
789 					return;
790 			}
791 		}
792 		RFS_SETCMD(rf_sc->sc_state,
793 		    (rfc_sc->sc_curbuf->b_flags & B_READ) != 0
794 		    ? RFS_RSEC : RFS_FBUF);
795 		break;
796 	case RFS_NOTINIT: /* Controller is idle and density is not detected. */
797 	case RFS_SMD:	/* Set Media Density */
798 	case RFS_RSTAT:	/* Read Status */
799 	case RFS_WDDS:	/* Write Deleted Data Sector */
800 	case RFS_REC:	/* Read Error Code */
801 	default:
802 		panic("Impossible state in rfc_intr(1).\n");
803 	}
804 
805 	if ((rfc_sc->sc_curbuf->b_flags & B_ERROR) != 0) {
806 		rfc_sc->sc_curbuf->b_error = EIO;
807 		biodone(rfc_sc->sc_curbuf);
808 		rfc_sc->sc_curbuf = NULL;
809 		RFS_SETCMD(rf_sc->sc_state, RFS_NOTINIT);
810 		return;
811 	}
812 
813 	/*
814 	 * ... then initiate next command.
815 	 */
816 	switch (rf_sc->sc_state & RFS_CMDS) {
817 	case RFS_NOTINIT: /* Controller is idle and density is not detected. */
818 	case RFS_PROBING: /* density detect / verify started */
819 	case RFS_IDLE:	/* controller is idle */
820 		panic("Impossible state in rfc_intr(2).\n");
821 		break;
822 	case RFS_EBUF:	/* Empty Buffer */
823 		i = bus_dmamap_load(rfc_sc->sc_dmat, rfc_sc->sc_dmam,
824 		    rfc_sc->sc_bufidx, (rf_sc->sc_state & RFS_DENS) == 0
825 		    ? RX2_BYTE_SD : RX2_BYTE_DD, rfc_sc->sc_curbuf->b_proc,
826 		    BUS_DMA_NOWAIT);
827 		if (i != 0) {
828 			printf("rfc_intr: Error while loading bus DMA map: "
829 			    "%d\n", i);
830 			rfc_sc->sc_curbuf->b_flags |= B_ERROR;
831 			break;
832 		}
833 		disk_busy(&rf_sc->sc_disk);
834 		if (rfc_sendcmd(rfc_sc, RX2CS_EBUF | RX2CS_IE
835 		    | ((rf_sc->sc_state & RFS_DENS) == 0 ? 0 : RX2CS_DD)
836 		    | (rf_sc->sc_dnum == 0 ? 0 : RX2CS_US)
837 		    | ((rfc_sc->sc_dmam->dm_segs[0].ds_addr & 0x30000)>>4),
838 		    ((rf_sc->sc_state & RFS_DENS) == 0
839 		    ? RX2_BYTE_SD : RX2_BYTE_DD) / 2,
840 		    rfc_sc->sc_dmam->dm_segs[0].ds_addr & 0xffff) < 0) {
841 			rfc_sc->sc_curbuf->b_flags |= B_ERROR;
842 			bus_dmamap_unload(rfc_sc->sc_dmat, rfc_sc->sc_dmam);
843 		}
844 		break;
845 	case RFS_FBUF:	/* Fill Buffer */
846 		i = bus_dmamap_load(rfc_sc->sc_dmat, rfc_sc->sc_dmam,
847 		    rfc_sc->sc_bufidx, (rf_sc->sc_state & RFS_DENS) == 0
848 		    ? RX2_BYTE_SD : RX2_BYTE_DD,
849 		    rfc_sc->sc_curbuf->b_proc, BUS_DMA_NOWAIT);
850 		if (i != 0) {
851 			printf("rfc_intr: Error while loading bus DMA map: "
852 			    "%d\n", i);
853 			rfc_sc->sc_curbuf->b_flags |= B_ERROR;
854 			break;
855 		}
856 		disk_busy(&rf_sc->sc_disk);
857 		if (rfc_sendcmd(rfc_sc, RX2CS_FBUF | RX2CS_IE
858 		    | ((rf_sc->sc_state & RFS_DENS) == 0 ? 0 : RX2CS_DD)
859 		    | (rf_sc->sc_dnum == 0 ? 0 : RX2CS_US)
860 		    | ((rfc_sc->sc_dmam->dm_segs[0].ds_addr & 0x30000)>>4),
861 		    ((rf_sc->sc_state & RFS_DENS) == 0
862 		    ? RX2_BYTE_SD : RX2_BYTE_DD) / 2,
863 		    rfc_sc->sc_dmam->dm_segs[0].ds_addr & 0xffff) < 0) {
864 			rfc_sc->sc_curbuf->b_flags |= B_ERROR;
865 			bus_dmamap_unload(rfc_sc->sc_dmat, rfc_sc->sc_dmam);
866 		}
867 		break;
868 	case RFS_WSEC:	/* Write Sector */
869 		i = (rfc_sc->sc_curbuf->b_bcount - rfc_sc->sc_bytesleft
870 		    + rfc_sc->sc_curbuf->b_blkno * DEV_BSIZE) /
871 		    ((rf_sc->sc_state & RFS_DENS) == 0
872 		    ? RX2_BYTE_SD : RX2_BYTE_DD);
873 		if (i > RX2_TRACKS * RX2_SECTORS) {
874 			rfc_sc->sc_curbuf->b_resid = rfc_sc->sc_bytesleft;
875 			rfc_sc->sc_curbuf->b_flags |= B_ERROR;
876 		}
877 		disk_busy(&rf_sc->sc_disk);
878 		if (rfc_sendcmd(rfc_sc, RX2CS_WSEC | RX2CS_IE
879 		    | (rf_sc->sc_dnum == 0 ? 0 : RX2CS_US)
880 		    | ((rf_sc->sc_state & RFS_DENS) == 0 ? 0 : RX2CS_DD),
881 		    i % RX2_SECTORS + 1, i / RX2_SECTORS) < 0) {
882 			rfc_sc->sc_curbuf->b_flags |= B_ERROR;
883 		}
884 		break;
885 	case RFS_RSEC:	/* Read Sector */
886 		i = (rfc_sc->sc_curbuf->b_bcount - rfc_sc->sc_bytesleft
887 		    + rfc_sc->sc_curbuf->b_blkno * DEV_BSIZE) /
888 		    ((rf_sc->sc_state & RFS_DENS) == 0
889 		    ? RX2_BYTE_SD : RX2_BYTE_DD);
890 		if (i > RX2_TRACKS * RX2_SECTORS) {
891 			rfc_sc->sc_curbuf->b_resid = rfc_sc->sc_bytesleft;
892 			rfc_sc->sc_curbuf->b_flags |= B_ERROR;
893 		}
894 		disk_busy(&rf_sc->sc_disk);
895 		if (rfc_sendcmd(rfc_sc, RX2CS_RSEC | RX2CS_IE
896 		    | (rf_sc->sc_dnum == 0 ? 0 : RX2CS_US)
897 		    | ((rf_sc->sc_state & RFS_DENS) == 0 ? 0 : RX2CS_DD),
898 		    i % RX2_SECTORS + 1, i / RX2_SECTORS) < 0) {
899 			rfc_sc->sc_curbuf->b_flags |= B_ERROR;
900 		}
901 		break;
902 	case RFS_SMD:	/* Set Media Density */
903 	case RFS_RSTAT:	/* Read Status */
904 	case RFS_WDDS:	/* Write Deleted Data Sector */
905 	case RFS_REC:	/* Read Error Code */
906 	default:
907 		panic("Impossible state in rfc_intr(3).\n");
908 	}
909 
910 	if ((rfc_sc->sc_curbuf->b_flags & B_ERROR) != 0) {
911 		rfc_sc->sc_curbuf->b_error = EIO;
912 		biodone(rfc_sc->sc_curbuf);
913 		rfc_sc->sc_curbuf = NULL;
914 		RFS_SETCMD(rf_sc->sc_state, RFS_NOTINIT);
915 	}
916 	return;
917 }
918 
919 
920 
921 int
922 rfdump(dev_t dev, daddr_t blkno, caddr_t va, size_t size)
923 {
924 
925 	/* A 0.5MB floppy is much to small to take a system dump... */
926 	return(ENXIO);
927 }
928 
929 
930 
931 int
932 rfsize(dev_t dev)
933 {
934 
935 	return(-1);
936 }
937 
938 
939 
940 int
941 rfopen(dev_t dev, int oflags, int devtype, struct proc *p)
942 {
943 	struct rf_softc *rf_sc;
944 	struct rfc_softc *rfc_sc;
945 	struct disklabel *dl;
946 	int unit;
947 
948 	unit = DISKUNIT(dev);
949 	if (unit >= rf_cd.cd_ndevs || (rf_sc = rf_cd.cd_devs[unit]) == NULL) {
950 		return(ENXIO);
951 	}
952 	rfc_sc = (struct rfc_softc *)rf_sc->sc_dev.dv_parent;
953 	dl = rf_sc->sc_disk.dk_label;
954 	switch (DISKPART(dev)) {
955 		case 0:			/* Part. a is single density. */
956 			rf_sc->sc_state &= ~RFS_DENS;
957 			rf_sc->sc_state &= ~RFS_AD;
958 		break;
959 		case 1:			/* Part. b is double density. */
960 			/*
961 			 * Opening a singe density only drive
962 			 * in double density is sensless.
963 			 */
964 			if (rfc_sc->type == 1) {
965 				return(ENXIO);
966 			}
967 			rf_sc->sc_state |= RFS_DENS;
968 			rf_sc->sc_state &= ~RFS_AD;
969 		break;
970 		case 2:			/* Part. c is auto density. */
971 			rf_sc->sc_state |= RFS_AD;
972 		break;
973 		default:
974 			return(ENXIO);
975 		break;
976 	}
977 	if ((rf_sc->sc_state & RFS_CMDS) == RFS_NOTINIT) {
978 		rfc_sc->sc_curchild = rf_sc->sc_dnum;
979 		/*
980 		 * Controller is idle and density is not detected.
981 		 * Start a density probe by issuing a read sector command
982 		 * and sleep until the density probe finished.
983 		 * Due to this it is imposible to open unformated media.
984 		 * As the RX02/02 is not able to format its own media,
985 		 * media must be purchased preformated. fsck DEC makreting!
986 		 */
987 		RFS_SETCMD(rf_sc->sc_state, RFS_PROBING);
988 		disk_busy(&rf_sc->sc_disk);
989 		if (rfc_sendcmd(rfc_sc, RX2CS_RSEC | RX2CS_IE
990 		    | (rf_sc->sc_dnum == 0 ? 0 : RX2CS_US)
991 		    | ((rf_sc->sc_state & RFS_DENS) == 0 ? 0 : RX2CS_DD),
992 		    1, 1) < 0) {
993 			rf_sc->sc_state = 0;
994 			return(ENXIO);
995 		}
996 		/* wait max. 2 sec for density probe to finish */
997 		if (tsleep(rf_sc, PRIBIO | PCATCH, "density probe", 2 * hz)
998 		    != 0 || (rf_sc->sc_state & RFS_CMDS) == RFS_NOTINIT) {
999 			/* timeout elapsed and / or somthing went wrong */
1000 			rf_sc->sc_state = 0;
1001 			return(ENXIO);
1002 		}
1003 	}
1004 	/* disklabel. We use different fake geometries for SD and DD. */
1005 	if ((rf_sc->sc_state & RFS_DENS) == 0) {
1006 		dl->d_nsectors = 10;		/* sectors per track */
1007 		dl->d_secpercyl = 10;		/* sectors per cylinder */
1008 		dl->d_ncylinders = 50;		/* cylinders per unit */
1009 		dl->d_secperunit = 501; /* sectors per unit */
1010 		/* number of sectors in partition */
1011 		dl->d_partitions[2].p_size = 500;
1012 	} else {
1013 		dl->d_nsectors = RX2_SECTORS / 2;  /* sectors per track */
1014 		dl->d_secpercyl = RX2_SECTORS / 2; /* sectors per cylinder */
1015 		dl->d_ncylinders = RX2_TRACKS;     /* cylinders per unit */
1016 		/* sectors per unit */
1017 		dl->d_secperunit = RX2_SECTORS * RX2_TRACKS / 2;
1018 		/* number of sectors in partition */
1019 		dl->d_partitions[2].p_size = RX2_SECTORS * RX2_TRACKS / 2;
1020 	}
1021 	rf_sc->sc_open++;
1022 	return(0);
1023 }
1024 
1025 
1026 
1027 int
1028 rfclose(dev_t dev, int fflag, int devtype, struct proc *p)
1029 {
1030 	struct rf_softc *rf_sc;
1031 	int unit;
1032 
1033 	unit = DISKUNIT(dev);
1034 	if (unit >= rf_cd.cd_ndevs || (rf_sc = rf_cd.cd_devs[unit]) == NULL) {
1035 		return(ENXIO);
1036 	}
1037 	if (rf_sc->sc_open == 0) {
1038 		panic("rfclose: can not close non-open drive %s",
1039 		    rf_sc->sc_dev.dv_xname);
1040 	} else {
1041 		if (--rf_sc->sc_open == 0) {
1042 			rf_sc->sc_state = 0;
1043 		}
1044 	}
1045 	return(0);
1046 }
1047 
1048 
1049 
1050 int
1051 rfread(dev_t dev, struct uio *uio, int ioflag)
1052 {
1053 
1054 	return(physio(rfstrategy, NULL, dev, B_READ, minphys, uio));
1055 }
1056 
1057 
1058 
1059 int
1060 rfwrite(dev_t dev, struct uio *uio, int ioflag)
1061 {
1062 
1063 	return(physio(rfstrategy, NULL, dev, B_WRITE, minphys, uio));
1064 }
1065 
1066 
1067 
1068 int
1069 rfioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
1070 {
1071 	struct rf_softc *rf_sc;
1072 	int unit;
1073 
1074 	unit = DISKUNIT(dev);
1075 	if (unit >= rf_cd.cd_ndevs || (rf_sc = rf_cd.cd_devs[unit]) == NULL) {
1076 		return(ENXIO);
1077 	}
1078 	/* We are going to operate on a non open dev? PANIC! */
1079 	if (rf_sc->sc_open == 0) {
1080 		panic("rfstrategy: can not operate on non-open drive %s (2)",
1081 		    rf_sc->sc_dev.dv_xname);
1082 	}
1083 	switch (cmd) {
1084 	/* get and set disklabel; DIOCGPART used internally */
1085 	case DIOCGDINFO: /* get */
1086 		memcpy(data, rf_sc->sc_disk.dk_label,
1087 		    sizeof(struct disklabel));
1088 		return(0);
1089 	case DIOCSDINFO: /* set */
1090 		return(0);
1091 	case DIOCWDINFO: /* set, update disk */
1092 		return(0);
1093 	case DIOCGPART:  /* get partition */
1094 		((struct partinfo *)data)->disklab = rf_sc->sc_disk.dk_label;
1095 		((struct partinfo *)data)->part =
1096 		    &rf_sc->sc_disk.dk_label->d_partitions[DISKPART(dev)];
1097 		return(0);
1098 
1099 	/* do format operation, read or write */
1100 	case DIOCRFORMAT:
1101 	break;
1102 	case DIOCWFORMAT:
1103 	break;
1104 
1105 	case DIOCSSTEP: /* set step rate */
1106 	break;
1107 	case DIOCSRETRIES: /* set # of retries */
1108 	break;
1109 	case DIOCKLABEL: /* keep/drop label on close? */
1110 	break;
1111 	case DIOCWLABEL: /* write en/disable label */
1112 	break;
1113 
1114 /*	case DIOCSBAD: / * set kernel dkbad */
1115 	break; /* */
1116 	case DIOCEJECT: /* eject removable disk */
1117 	break;
1118 	case ODIOCEJECT: /* eject removable disk */
1119 	break;
1120 	case DIOCLOCK: /* lock/unlock pack */
1121 	break;
1122 
1123 	/* get default label, clear label */
1124 	case DIOCGDEFLABEL:
1125 	break;
1126 	case DIOCCLRLABEL:
1127 	break;
1128 	default:
1129 		return(ENOTTY);
1130 	}
1131 
1132 	return(ENOTTY);
1133 }
1134 
1135 
1136