xref: /openbsd/sys/arch/octeon/dev/octcf.c (revision 3cab2bb3)
1 /*	$OpenBSD: octcf.c,v 1.32 2018/05/30 14:53:56 fcambus Exp $ */
2 /*	$NetBSD: wd.c,v 1.193 1999/02/28 17:15:27 explorer Exp $ */
3 
4 /*
5  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *	notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *	notice, this list of conditions and the following disclaimer in the
14  *	documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*-
29  * Copyright (c) 1998 The NetBSD Foundation, Inc.
30  * All rights reserved.
31  *
32  * This code is derived from software contributed to The NetBSD Foundation
33  * by Charles M. Hannum and by Onno van der Linden.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  * 1. Redistributions of source code must retain the above copyright
39  *    notice, this list of conditions and the following disclaimer.
40  * 2. Redistributions in binary form must reproduce the above copyright
41  *    notice, this list of conditions and the following disclaimer in the
42  *    documentation and/or other materials provided with the distribution.
43  *
44  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
45  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
46  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
47  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
48  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
49  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
50  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
51  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
52  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
54  * POSSIBILITY OF SUCH DAMAGE.
55  */
56 
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/kernel.h>
60 #include <sys/conf.h>
61 #include <sys/fcntl.h>
62 #include <sys/stat.h>
63 #include <sys/ioctl.h>
64 #include <sys/mutex.h>
65 #include <sys/buf.h>
66 #include <sys/uio.h>
67 #include <sys/malloc.h>
68 #include <sys/device.h>
69 #include <sys/disklabel.h>
70 #include <sys/disk.h>
71 #include <sys/syslog.h>
72 #include <sys/proc.h>
73 #include <sys/vnode.h>
74 #include <sys/dkio.h>
75 
76 #include <machine/intr.h>
77 #include <machine/bus.h>
78 
79 #include <dev/ata/atareg.h>
80 #include <dev/ata/atavar.h>
81 #include <dev/ic/wdcreg.h>
82 #include <dev/ic/wdcvar.h>
83 
84 #include <octeon/dev/iobusvar.h>
85 #include <machine/octeonreg.h>
86 #include <machine/octeonvar.h>
87 
88 #define OCTCF_REG_SIZE	8
89 #define ATAPARAMS_SIZE	512
90 #define SECTOR_SIZE	512
91 #define OCTCFDELAY	100 /* 100 microseconds */
92 #define NR_TRIES	1000
93 
94 #define DEBUG_XFERS  0x02
95 #define DEBUG_FUNCS  0x08
96 #define DEBUG_PROBE  0x10
97 
98 #ifdef OCTCFDEBUG
99 int octcfdebug_mask = 0xff;
100 #define OCTCFDEBUG_PRINT(args, level) do {	\
101 	if ((octcfdebug_mask & (level)) != 0)	\
102 		printf args;			\
103 } while (0)
104 #else
105 #define OCTCFDEBUG_PRINT(args, level)
106 #endif
107 
108 struct octcf_softc {
109 	/* General disk infos */
110 	struct device sc_dev;
111 	struct disk sc_dk;
112 	struct bufq sc_bufq;
113 	struct buf *sc_bp;
114 	struct ataparams sc_params;/* drive characteristics found */
115 	int sc_flags;
116 #define OCTCFF_LOADED		0x10 /* parameters loaded */
117 	u_int64_t sc_capacity;
118 	bus_space_tag_t       sc_iot;
119 	bus_space_handle_t    sc_ioh;
120 };
121 
122 int	octcfprobe(struct device *, void *, void *);
123 void	octcfattach(struct device *, struct device *, void *);
124 int	octcfdetach(struct device *, int);
125 int	octcfactivate(struct device *, int);
126 int	octcfprint(void *, char *);
127 
128 struct cfattach octcf_ca = {
129 	sizeof(struct octcf_softc), octcfprobe, octcfattach,
130 	octcfdetach, octcfactivate
131 };
132 
133 struct cfdriver octcf_cd = {
134 	NULL, "octcf", DV_DISK
135 };
136 
137 void  octcfgetdefaultlabel(struct octcf_softc *, struct disklabel *);
138 int   octcfgetdisklabel(dev_t dev, struct octcf_softc *, struct disklabel *, int);
139 void  octcfstrategy(struct buf *);
140 void  octcfstart(void *);
141 void  _octcfstart(struct octcf_softc*, struct buf *);
142 void  octcfdone(void *);
143 
144 cdev_decl(octcf);
145 bdev_decl(octcf);
146 
147 #define octcflookup(unit) (struct octcf_softc *)disk_lookup(&octcf_cd, (unit))
148 
149 int	octcf_write_sectors(struct octcf_softc *, uint32_t, uint32_t, void *);
150 int	octcf_read_sectors(struct octcf_softc *, uint32_t, uint32_t, void *);
151 int	octcf_wait_busy(struct octcf_softc *);
152 void	octcf_command(struct octcf_softc *, uint32_t, uint8_t);
153 int 	octcf_get_params(struct octcf_softc *, struct ataparams *);
154 
155 #define OCTCF_REG_READ(wd, reg) \
156 	bus_space_read_2(wd->sc_iot, wd->sc_ioh, reg & 0x6)
157 #define OCTCF_REG_WRITE(wd, reg, val) \
158 	bus_space_write_2(wd->sc_iot, wd->sc_ioh, reg & 0x6, val)
159 
160 int
161 octcfprobe(struct device *parent, void *match, void *aux)
162 {
163 	if (octeon_boot_info->cf_common_addr == 0) {
164 		OCTCFDEBUG_PRINT(("%s: No cf bus found\n", __func__), DEBUG_FUNCS | DEBUG_PROBE);
165 		return 0;
166 	}
167 
168 	return 1;
169 }
170 
171 void
172 octcfattach(struct device *parent, struct device *self, void *aux)
173 {
174 	struct octcf_softc *wd = (void *)self;
175 	struct iobus_attach_args *aa = aux;
176 	int i, blank;
177 	char buf[41], c, *p, *q;
178 	uint8_t status;
179 	OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS | DEBUG_PROBE);
180 
181 	wd->sc_iot = aa->aa_bust;
182 
183 	if (bus_space_map(wd->sc_iot, aa->aa_addr,
184 	    OCTCF_REG_SIZE, BUS_SPACE_MAP_KSEG0, &wd->sc_ioh)) {
185 		printf(": couldn't map registers\n");
186 		return;
187 	}
188 
189 	for (i = 0; i < 8; i++) {
190 		uint64_t cfg =
191 		*(uint64_t *)PHYS_TO_XKPHYS(
192 			OCTEON_MIO_BOOT_BASE + MIO_BOOT_REG_CFG(i), CCA_NC);
193 
194 		if ((cfg & BOOT_CFG_BASE_MASK) ==
195 			(OCTEON_CF_BASE >> BOOT_CFG_BASE_SHIFT)) {
196 			if ((cfg & BOOT_CFG_WIDTH_MASK) == 0)
197 				printf(": doesn't support 8bit cards\n");
198 			break;
199 		}
200 	}
201 
202 	/* Check if CF is inserted */
203 	i = 0;
204 	while ( (status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY) {
205 		if ((i++) == NR_TRIES )     {
206 			printf(": card not present\n");
207 			return;
208                	}
209 		DELAY(OCTCFDELAY);
210 	}
211 
212 	/* read our drive info */
213 	if (octcf_get_params(wd, &wd->sc_params) != 0) {
214 		printf(": IDENTIFY failed\n");
215 		return;
216 	}
217 
218 	for (blank = 0, p = wd->sc_params.atap_model, q = buf, i = 0;
219 	    i < sizeof(wd->sc_params.atap_model); i++) {
220 		c = *p++;
221 		if (c == '\0')
222 			break;
223 		if (c != ' ') {
224 			if (blank) {
225 				*q++ = ' ';
226 				blank = 0;
227 			}
228 			*q++ = c;
229 		} else
230 			blank = 1;
231 		}
232 	*q++ = '\0';
233 
234 	printf(": <%s>\n", buf);
235 	printf("%s: %d-sector PIO,",
236 		wd->sc_dev.dv_xname, wd->sc_params.atap_multi & 0xff);
237 
238 	wd->sc_capacity =
239 		wd->sc_params.atap_cylinders *
240 		wd->sc_params.atap_heads *
241 		wd->sc_params.atap_sectors;
242 	printf(" CHS, %lluMB, %d cyl, %d head, %d sec, %llu sectors\n",
243 		wd->sc_capacity / (1048576 / DEV_BSIZE),
244 		wd->sc_params.atap_cylinders,
245 		wd->sc_params.atap_heads,
246 		wd->sc_params.atap_sectors,
247 		wd->sc_capacity);
248 
249 	OCTCFDEBUG_PRINT(
250 		("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n",
251 		self->dv_xname, wd->sc_params.atap_dmatiming_mimi,
252 		wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE);
253 
254 	/*
255 	 * Initialize disk structures.
256 	 */
257 	wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
258 	bufq_init(&wd->sc_bufq, BUFQ_DEFAULT);
259 
260 	/* Attach disk. */
261 	disk_attach(&wd->sc_dev, &wd->sc_dk);
262 }
263 
264 int
265 octcfactivate(struct device *self, int act)
266 {
267 	return 0;
268 }
269 
270 int
271 octcfdetach(struct device *self, int flags)
272 {
273 	struct octcf_softc *sc = (struct octcf_softc *)self;
274 
275 	bufq_drain(&sc->sc_bufq);
276 
277 	disk_gone(octcfopen, self->dv_unit);
278 
279 	/* Detach disk. */
280 	bufq_destroy(&sc->sc_bufq);
281 	disk_detach(&sc->sc_dk);
282 
283 	return (0);
284 }
285 
286 /*
287  * Read/write routine for a buffer.  Validates the arguments and schedules the
288  * transfer.  Does not wait for the transfer to complete.
289  */
290 void
291 octcfstrategy(struct buf *bp)
292 {
293 	struct octcf_softc *wd;
294 	int s;
295 
296 	wd = octcflookup(DISKUNIT(bp->b_dev));
297 	if (wd == NULL) {
298 		bp->b_error = ENXIO;
299 		goto bad;
300 	}
301 
302 	OCTCFDEBUG_PRINT(("%s (%s)\n", __func__, wd->sc_dev.dv_xname),
303 	    DEBUG_XFERS);
304 
305 	/* If device invalidated (e.g. media change, door open), error. */
306 	if ((wd->sc_flags & OCTCFF_LOADED) == 0) {
307 		bp->b_error = EIO;
308 		goto bad;
309 	}
310 
311 	/* Validate the request. */
312 	if (bounds_check_with_label(bp, wd->sc_dk.dk_label) == -1)
313 		goto done;
314 
315 	/* Check that the number of sectors can fit in a byte. */
316 	if ((bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) {
317 		bp->b_error = EINVAL;
318 		goto bad;
319 	}
320 
321 	/* Queue transfer on drive, activate drive and controller if idle. */
322 	bufq_queue(&wd->sc_bufq, bp);
323 	s = splbio();
324 	octcfstart(wd);
325 	splx(s);
326 	device_unref(&wd->sc_dev);
327 	return;
328 
329  bad:
330 	bp->b_flags |= B_ERROR;
331 	bp->b_resid = bp->b_bcount;
332  done:
333 	s = splbio();
334 	biodone(bp);
335 	splx(s);
336 	if (wd != NULL)
337 		device_unref(&wd->sc_dev);
338 }
339 
340 /*
341  * Queue a drive for I/O.
342  */
343 void
344 octcfstart(void *arg)
345 {
346 	struct octcf_softc *wd = arg;
347 	struct buf *bp;
348 
349 	OCTCFDEBUG_PRINT(("%s %s\n", __func__, wd->sc_dev.dv_xname),
350 	    DEBUG_XFERS);
351 	while ((bp = bufq_dequeue(&wd->sc_bufq)) != NULL) {
352 		/* Transfer this buffer now. */
353 		_octcfstart(wd, bp);
354 	}
355 }
356 
357 void
358 _octcfstart(struct octcf_softc *wd, struct buf *bp)
359 {
360 	struct disklabel *lp;
361 	u_int64_t secno;
362 	u_int64_t nsecs;
363 
364 	lp = wd->sc_dk.dk_label;
365 	secno = DL_BLKTOSEC(lp, bp->b_blkno) +
366 	    DL_GETPOFFSET(&lp->d_partitions[DISKPART(bp->b_dev)]);
367 	nsecs = howmany(bp->b_bcount, lp->d_secsize);
368 	wd->sc_bp = bp;
369 
370 	/* Instrumentation. */
371 	disk_busy(&wd->sc_dk);
372 
373 	if (bp->b_flags & B_READ)
374 		bp->b_error = octcf_read_sectors(wd, nsecs, secno, bp->b_data);
375 	else
376 		bp->b_error = octcf_write_sectors(wd, nsecs, secno, bp->b_data);
377 
378 	octcfdone(wd);
379 }
380 
381 void
382 octcfdone(void *arg)
383 {
384 	struct octcf_softc *wd = arg;
385 	struct buf *bp = wd->sc_bp;
386 
387 	if (bp->b_error == 0)
388 		bp->b_resid = 0;
389 	else
390 		bp->b_flags |= B_ERROR;
391 
392 	disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid),
393 	    bp->b_blkno, (bp->b_flags & B_READ));
394 	biodone(bp);
395 }
396 
397 int
398 octcfread(dev_t dev, struct uio *uio, int flags)
399 {
400 
401 	OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_XFERS);
402 	return (physio(octcfstrategy, dev, B_READ, minphys, uio));
403 }
404 
405 int
406 octcfwrite(dev_t dev, struct uio *uio, int flags)
407 {
408 
409 	OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_XFERS);
410 	return (physio(octcfstrategy, dev, B_WRITE, minphys, uio));
411 }
412 
413 int
414 octcfopen(dev_t dev, int flag, int fmt, struct proc *p)
415 {
416 	struct octcf_softc *wd;
417 	int unit, part;
418 	int error;
419 
420 	OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
421 
422 	unit = DISKUNIT(dev);
423 	wd = octcflookup(unit);
424 	if (wd == NULL)
425 		return ENXIO;
426 
427 	/*
428 	 * If this is the first open of this device, add a reference
429 	 * to the adapter.
430 	 */
431 	if ((error = disk_lock(&wd->sc_dk)) != 0)
432 		goto bad4;
433 
434 	if (wd->sc_dk.dk_openmask != 0) {
435 		/*
436 		 * If any partition is open, but the disk has been invalidated,
437 		 * disallow further opens.
438 		 */
439 		if ((wd->sc_flags & OCTCFF_LOADED) == 0) {
440 			error = EIO;
441 			goto bad3;
442 		}
443 	} else {
444 		if ((wd->sc_flags & OCTCFF_LOADED) == 0) {
445 			wd->sc_flags |= OCTCFF_LOADED;
446 
447 			/* Load the physical device parameters. */
448 			octcf_get_params(wd, &wd->sc_params);
449 
450 			/* Load the partition info if not already loaded. */
451 			if (octcfgetdisklabel(dev, wd,
452 			    wd->sc_dk.dk_label, 0) == EIO) {
453 				error = EIO;
454 				goto bad;
455 			}
456 		}
457 	}
458 
459 	part = DISKPART(dev);
460 
461 	if ((error = disk_openpart(&wd->sc_dk, part, fmt, 1)) != 0)
462 		goto bad;
463 
464 	disk_unlock(&wd->sc_dk);
465 	device_unref(&wd->sc_dev);
466 	return 0;
467 
468 bad:
469 	if (wd->sc_dk.dk_openmask == 0) {
470 	}
471 
472 bad3:
473 	disk_unlock(&wd->sc_dk);
474 bad4:
475 	device_unref(&wd->sc_dev);
476 	return error;
477 }
478 
479 int
480 octcfclose(dev_t dev, int flag, int fmt, struct proc *p)
481 {
482 	struct octcf_softc *wd;
483 	int part = DISKPART(dev);
484 
485 	wd = octcflookup(DISKUNIT(dev));
486 	if (wd == NULL)
487 		return ENXIO;
488 
489 	OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
490 
491 	disk_lock_nointr(&wd->sc_dk);
492 
493 	disk_closepart(&wd->sc_dk, part, fmt);
494 
495 	disk_unlock(&wd->sc_dk);
496 
497 	device_unref(&wd->sc_dev);
498 	return (0);
499 }
500 
501 void
502 octcfgetdefaultlabel(struct octcf_softc *wd, struct disklabel *lp)
503 {
504 	OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
505 	bzero(lp, sizeof(struct disklabel));
506 
507 	lp->d_secsize = DEV_BSIZE;
508 	DL_SETDSIZE(lp, wd->sc_capacity);
509 	lp->d_ntracks = wd->sc_params.atap_heads;
510 	lp->d_nsectors = wd->sc_params.atap_sectors;
511 	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
512 	lp->d_ncylinders = DL_GETDSIZE(lp) / lp->d_secpercyl;
513 	lp->d_type = DTYPE_ESDI;
514 	strncpy(lp->d_typename, "ESDI/IDE disk", sizeof lp->d_typename);
515 
516 	/* XXX - user viscopy() like sd.c */
517 	strncpy(lp->d_packname, wd->sc_params.atap_model, sizeof lp->d_packname);
518 	lp->d_flags = 0;
519 	lp->d_version = 1;
520 
521 	lp->d_magic = DISKMAGIC;
522 	lp->d_magic2 = DISKMAGIC;
523 	lp->d_checksum = dkcksum(lp);
524 }
525 
526 /*
527  * Fabricate a default disk label, and try to read the correct one.
528  */
529 int
530 octcfgetdisklabel(dev_t dev, struct octcf_softc *wd, struct disklabel *lp,
531     int spoofonly)
532 {
533 	int error;
534 
535 	OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
536 
537 	octcfgetdefaultlabel(wd, lp);
538 	error = readdisklabel(DISKLABELDEV(dev), octcfstrategy, lp,
539 	    spoofonly);
540 	return (error);
541 }
542 
543 int
544 octcfioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, struct proc *p)
545 {
546 	struct octcf_softc *wd;
547 	struct disklabel *lp;
548 	int error = 0;
549 
550 	OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
551 
552 	wd = octcflookup(DISKUNIT(dev));
553 	if (wd == NULL)
554 		return ENXIO;
555 
556 	if ((wd->sc_flags & OCTCFF_LOADED) == 0) {
557 		error = EIO;
558 		goto exit;
559 	}
560 
561 	switch (xfer) {
562 	case DIOCRLDINFO:
563 		lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK);
564 		octcfgetdisklabel(dev, wd, lp, 0);
565 		bcopy(lp, wd->sc_dk.dk_label, sizeof(*lp));
566 		free(lp, M_TEMP, sizeof(*lp));
567 		goto exit;
568 
569 	case DIOCGPDINFO:
570 		octcfgetdisklabel(dev, wd, (struct disklabel *)addr, 1);
571 		goto exit;
572 
573 	case DIOCGDINFO:
574 		*(struct disklabel *)addr = *(wd->sc_dk.dk_label);
575 		goto exit;
576 
577 	case DIOCGPART:
578 		((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label;
579 		((struct partinfo *)addr)->part =
580 		    &wd->sc_dk.dk_label->d_partitions[DISKPART(dev)];
581 		goto exit;
582 
583 	case DIOCWDINFO:
584 	case DIOCSDINFO:
585 		if ((flag & FWRITE) == 0) {
586 			error = EBADF;
587 			goto exit;
588 		}
589 
590 		if ((error = disk_lock(&wd->sc_dk)) != 0)
591 			goto exit;
592 
593 		error = setdisklabel(wd->sc_dk.dk_label,
594 		    (struct disklabel *)addr, wd->sc_dk.dk_openmask);
595 		if (error == 0) {
596 			if (xfer == DIOCWDINFO)
597 				error = writedisklabel(DISKLABELDEV(dev),
598 				    octcfstrategy, wd->sc_dk.dk_label);
599 		}
600 
601 		disk_unlock(&wd->sc_dk);
602 		goto exit;
603 
604 	default:
605 		error = ENOTTY;
606 		goto exit;
607 	}
608 
609 #ifdef DIAGNOSTIC
610 	panic("octcfioctl: impossible");
611 #endif
612 
613  exit:
614 	device_unref(&wd->sc_dev);
615 	return (error);
616 }
617 
618 #ifdef B_FORMAT
619 int
620 wdformat(struct buf *bp)
621 {
622 	bp->b_flags |= B_FORMAT;
623 	return octcfstrategy(bp);
624 }
625 #endif
626 
627 daddr_t
628 octcfsize(dev_t dev)
629 {
630 	struct octcf_softc *wd;
631 	struct disklabel *lp;
632 	int part, omask;
633 	daddr_t size;
634 
635 	OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
636 
637 	wd = octcflookup(DISKUNIT(dev));
638 	if (wd == NULL)
639 		return (-1);
640 
641 	part = DISKPART(dev);
642 	omask = wd->sc_dk.dk_openmask & (1 << part);
643 
644 	if (omask == 0 && octcfopen(dev, 0, S_IFBLK, NULL) != 0) {
645 		size = -1;
646 		goto exit;
647 	}
648 
649 	lp = wd->sc_dk.dk_label;
650 	size = DL_SECTOBLK(lp, DL_GETPSIZE(&lp->d_partitions[part]));
651 	if (omask == 0 && octcfclose(dev, 0, S_IFBLK, NULL) != 0)
652 		size = -1;
653 
654  exit:
655 	device_unref(&wd->sc_dev);
656 	return (size);
657 }
658 
659 /*
660  * Dump core after a system crash.
661  */
662 int
663 octcfdump(dev_t dev, daddr_t blkno, caddr_t va, size_t size)
664 {
665 	return ENXIO;
666 }
667 
668 int
669 octcf_read_sectors(struct octcf_softc *wd, uint32_t nr_sectors,
670 	uint32_t start_sector, void *buf)
671 {
672 	uint32_t count;
673 	uint16_t *ptr = (uint16_t*)buf;
674 	int error;
675 	uint8_t status;
676 
677 	while (nr_sectors--) {
678 		while ((status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY)
679 			DELAY(OCTCFDELAY);
680 		octcf_command(wd, start_sector++, WDCC_READ);
681 		error = octcf_wait_busy(wd);
682 		if (error != 0)
683 			return (error);
684 
685         	volatile uint16_t dummy;
686 		for (count = 0; count < SECTOR_SIZE; count+=2) {
687 			uint16_t temp;
688 			temp = OCTCF_REG_READ(wd, 0x0);
689 			*ptr++ = swap16(temp);
690 			if ((count & 0xf) == 0)
691 				dummy = OCTCF_REG_READ(wd, wdr_status);
692 		}
693 	}
694 	return (0);
695 }
696 
697 int
698 octcf_write_sectors(struct octcf_softc *wd, uint32_t nr_sectors,
699 	uint32_t start_sector, void *buf)
700 {
701 	uint32_t count;
702 	uint16_t *ptr = (uint16_t*)buf;
703 	int error;
704 	uint8_t status;
705 
706 	while (nr_sectors--) {
707 		while ((status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY)
708 			DELAY(OCTCFDELAY);
709 		octcf_command(wd, start_sector++, WDCC_WRITE);
710 		if((error = octcf_wait_busy(wd)))
711 			return (error);
712 
713 	      	volatile uint16_t dummy;
714 		for (count = 0; count < SECTOR_SIZE; count+=2) {
715 			uint16_t temp = *ptr++;
716 			OCTCF_REG_WRITE(wd, 0x0, swap16(temp));
717 			if ((count & 0xf) == 0)
718 				dummy = OCTCF_REG_READ(wd, wdr_status);
719 		}
720 	}
721 	return (0);
722 }
723 
724 void
725 octcf_command(struct octcf_softc *wd, uint32_t lba, uint8_t cmd)
726 {
727 	OCTCF_REG_WRITE(wd, wdr_seccnt, 1 | ((lba & 0xff) << 8));
728 	OCTCF_REG_WRITE(wd, wdr_cyl_lo,
729 		((lba >> 8) & 0xff) | (((lba >> 16) & 0xff) << 8));
730 	OCTCF_REG_WRITE(wd, wdr_sdh,
731 		(((lba >> 24) & 0xff) | 0xe0) | (cmd << 8));
732 }
733 
734 int
735 octcf_wait_busy(struct octcf_softc *wd)
736 {
737 	uint8_t status;
738 
739 	status = OCTCF_REG_READ(wd, wdr_status)>>8;
740 	while ((status & WDCS_BSY) == WDCS_BSY) {
741 		if ((status & WDCS_DWF) != 0)
742 			return (EIO);
743 		DELAY(OCTCFDELAY);
744 		status = (uint8_t)(OCTCF_REG_READ(wd, wdr_status)>>8);
745 	}
746 
747 	if ((status & WDCS_DRQ) == 0)
748 		return (ENXIO);
749 
750 	return (0);
751 }
752 
753 /* Get the disk's parameters */
754 int
755 octcf_get_params(struct octcf_softc *wd, struct ataparams *params)
756 {
757 	char *tb;
758 	int i;
759 	u_int16_t *p;
760 	int count;
761 	uint8_t status;
762 	int error;
763 
764 	OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
765 
766 	tb = malloc(ATAPARAMS_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO);
767 	if (tb == NULL)
768 		return CMD_AGAIN;
769 
770 	while ((status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY)
771 		DELAY(OCTCFDELAY);
772 
773 	OCTCF_REG_WRITE(wd, wdr_seccnt, 0);
774 	OCTCF_REG_WRITE(wd, wdr_cyl_lo, 0);
775 	OCTCF_REG_WRITE(wd, wdr_sdh, 0 | (WDCC_IDENTIFY<<8));
776 
777 	error = octcf_wait_busy(wd);
778 	if (error == 0) {
779 		for (count = 0; count < SECTOR_SIZE; count+=2) {
780 			uint16_t temp;
781 			temp = OCTCF_REG_READ(wd, 0x0);
782 
783 			/* endianess will be swapped below */
784 			tb[count]   = (temp & 0xff);
785 			tb[count+1] = (temp & 0xff00)>>8;
786 		}
787 	}
788 
789 	if (error != 0) {
790 		printf("%s: identify failed: %d\n", __func__, error);
791 		free(tb, M_DEVBUF, ATAPARAMS_SIZE);
792 		return CMD_ERR;
793 	} else {
794 		/*
795 		 * All the fields in the params structure are 16-bit
796 		 * integers except for the ID strings which are char
797 		 * strings.  The 16-bit integers are currently in
798 		 * memory in little-endian, regardless of architecture.
799 		 * So, they need to be swapped on big-endian architectures
800 		 * before they are accessed through the ataparams structure.
801 		 *
802 		 * The swaps below avoid touching the char strings.
803 		*/
804 		swap16_multi((u_int16_t *)tb, 10);
805 		swap16_multi((u_int16_t *)tb + 20, 3);
806 		swap16_multi((u_int16_t *)tb + 47, ATAPARAMS_SIZE / 2 - 47);
807 
808 		/* Read in parameter block. */
809 		bcopy(tb, params, sizeof(struct ataparams));
810 
811 		/*
812 		 * Shuffle string byte order.
813 		 * ATAPI Mitsumi and NEC drives don't need this.
814 		 */
815 		if ((params->atap_config & WDC_CFG_ATAPI_MASK) ==
816 		    WDC_CFG_ATAPI &&
817 		    ((params->atap_model[0] == 'N' &&
818 			params->atap_model[1] == 'E') ||
819 		     (params->atap_model[0] == 'F' &&
820 			 params->atap_model[1] == 'X'))) {
821 			free(tb, M_DEVBUF, ATAPARAMS_SIZE);
822 			return CMD_OK;
823 		}
824 		for (i = 0; i < sizeof(params->atap_model); i += 2) {
825 			p = (u_short *)(params->atap_model + i);
826 			*p = swap16(*p);
827 		}
828 		for (i = 0; i < sizeof(params->atap_serial); i += 2) {
829 			p = (u_short *)(params->atap_serial + i);
830 			*p = swap16(*p);
831 		}
832 		for (i = 0; i < sizeof(params->atap_revision); i += 2) {
833 			p = (u_short *)(params->atap_revision + i);
834 			*p = swap16(*p);
835 		}
836 
837 		free(tb, M_DEVBUF, ATAPARAMS_SIZE);
838 		return CMD_OK;
839 	}
840 }
841