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