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