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