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