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