1 /* $OpenBSD: octcf.c,v 1.36 2024/05/20 23:13:33 jsg 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
127 const struct cfattach octcf_ca = {
128 sizeof(struct octcf_softc), octcfprobe, octcfattach,
129 octcfdetach, octcfactivate
130 };
131
132 struct cfdriver octcf_cd = {
133 NULL, "octcf", DV_DISK
134 };
135
136 void octcfgetdefaultlabel(struct octcf_softc *, struct disklabel *);
137 int octcfgetdisklabel(dev_t dev, struct octcf_softc *, struct disklabel *, int);
138 void octcfstrategy(struct buf *);
139 void octcfstart(void *);
140 void _octcfstart(struct octcf_softc*, struct buf *);
141 void octcfdone(void *);
142
143 cdev_decl(octcf);
144 bdev_decl(octcf);
145
146 #define octcflookup(unit) (struct octcf_softc *)disk_lookup(&octcf_cd, (unit))
147
148 int octcf_write_sectors(struct octcf_softc *, uint32_t, uint32_t, void *);
149 int octcf_read_sectors(struct octcf_softc *, uint32_t, uint32_t, void *);
150 int octcf_wait_busy(struct octcf_softc *);
151 void octcf_command(struct octcf_softc *, uint32_t, uint8_t);
152 int octcf_get_params(struct octcf_softc *, struct ataparams *);
153
154 #define OCTCF_REG_READ(wd, reg) \
155 bus_space_read_2(wd->sc_iot, wd->sc_ioh, reg & 0x6)
156 #define OCTCF_REG_WRITE(wd, reg, val) \
157 bus_space_write_2(wd->sc_iot, wd->sc_ioh, reg & 0x6, val)
158
159 int
octcfprobe(struct device * parent,void * match,void * aux)160 octcfprobe(struct device *parent, void *match, void *aux)
161 {
162 if (octeon_boot_info->cf_common_addr == 0) {
163 OCTCFDEBUG_PRINT(("%s: No cf bus found\n", __func__), DEBUG_FUNCS | DEBUG_PROBE);
164 return 0;
165 }
166
167 return 1;
168 }
169
170 void
octcfattach(struct device * parent,struct device * self,void * aux)171 octcfattach(struct device *parent, struct device *self, void *aux)
172 {
173 struct octcf_softc *wd = (void *)self;
174 struct iobus_attach_args *aa = aux;
175 int i, blank;
176 char buf[41], c, *p, *q;
177 uint8_t status;
178 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS | DEBUG_PROBE);
179
180 wd->sc_iot = aa->aa_bust;
181
182 if (bus_space_map(wd->sc_iot, aa->aa_addr,
183 OCTCF_REG_SIZE, BUS_SPACE_MAP_KSEG0, &wd->sc_ioh)) {
184 printf(": couldn't map registers\n");
185 return;
186 }
187
188 for (i = 0; i < 8; i++) {
189 uint64_t cfg =
190 *(uint64_t *)PHYS_TO_XKPHYS(
191 OCTEON_MIO_BOOT_BASE + MIO_BOOT_REG_CFG(i), CCA_NC);
192
193 if ((cfg & BOOT_CFG_BASE_MASK) ==
194 (OCTEON_CF_BASE >> BOOT_CFG_BASE_SHIFT)) {
195 if ((cfg & BOOT_CFG_WIDTH_MASK) == 0)
196 printf(": doesn't support 8bit cards\n");
197 break;
198 }
199 }
200
201 /* Check if CF is inserted */
202 i = 0;
203 while ( (status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY) {
204 if ((i++) == NR_TRIES ) {
205 printf(": card not present\n");
206 return;
207 }
208 DELAY(OCTCFDELAY);
209 }
210
211 /* read our drive info */
212 if (octcf_get_params(wd, &wd->sc_params) != 0) {
213 printf(": IDENTIFY failed\n");
214 return;
215 }
216
217 for (blank = 0, p = wd->sc_params.atap_model, q = buf, i = 0;
218 i < sizeof(wd->sc_params.atap_model); i++) {
219 c = *p++;
220 if (c == '\0')
221 break;
222 if (c != ' ') {
223 if (blank) {
224 *q++ = ' ';
225 blank = 0;
226 }
227 *q++ = c;
228 } else
229 blank = 1;
230 }
231 *q++ = '\0';
232
233 printf(": <%s>\n", buf);
234 printf("%s: %d-sector PIO,",
235 wd->sc_dev.dv_xname, wd->sc_params.atap_multi & 0xff);
236
237 wd->sc_capacity =
238 wd->sc_params.atap_cylinders *
239 wd->sc_params.atap_heads *
240 wd->sc_params.atap_sectors;
241 printf(" CHS, %lluMB, %d cyl, %d head, %d sec, %llu sectors\n",
242 wd->sc_capacity / (1048576 / DEV_BSIZE),
243 wd->sc_params.atap_cylinders,
244 wd->sc_params.atap_heads,
245 wd->sc_params.atap_sectors,
246 wd->sc_capacity);
247
248 OCTCFDEBUG_PRINT(
249 ("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n",
250 self->dv_xname, wd->sc_params.atap_dmatiming_mimi,
251 wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE);
252
253 /*
254 * Initialize disk structures.
255 */
256 wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
257 bufq_init(&wd->sc_bufq, BUFQ_DEFAULT);
258
259 /* Attach disk. */
260 disk_attach(&wd->sc_dev, &wd->sc_dk);
261 }
262
263 int
octcfactivate(struct device * self,int act)264 octcfactivate(struct device *self, int act)
265 {
266 return 0;
267 }
268
269 int
octcfdetach(struct device * self,int flags)270 octcfdetach(struct device *self, int flags)
271 {
272 struct octcf_softc *sc = (struct octcf_softc *)self;
273
274 bufq_drain(&sc->sc_bufq);
275
276 disk_gone(octcfopen, self->dv_unit);
277
278 /* Detach disk. */
279 bufq_destroy(&sc->sc_bufq);
280 disk_detach(&sc->sc_dk);
281
282 return (0);
283 }
284
285 /*
286 * Read/write routine for a buffer. Validates the arguments and schedules the
287 * transfer. Does not wait for the transfer to complete.
288 */
289 void
octcfstrategy(struct buf * bp)290 octcfstrategy(struct buf *bp)
291 {
292 struct octcf_softc *wd;
293 int s;
294
295 wd = octcflookup(DISKUNIT(bp->b_dev));
296 if (wd == NULL) {
297 bp->b_error = ENXIO;
298 goto bad;
299 }
300
301 OCTCFDEBUG_PRINT(("%s (%s)\n", __func__, wd->sc_dev.dv_xname),
302 DEBUG_XFERS);
303
304 /* If device invalidated (e.g. media change, door open), error. */
305 if ((wd->sc_flags & OCTCFF_LOADED) == 0) {
306 bp->b_error = EIO;
307 goto bad;
308 }
309
310 /* Validate the request. */
311 if (bounds_check_with_label(bp, wd->sc_dk.dk_label) == -1)
312 goto done;
313
314 /* Check that the number of sectors can fit in a byte. */
315 if ((bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) {
316 bp->b_error = EINVAL;
317 goto bad;
318 }
319
320 /* Queue transfer on drive, activate drive and controller if idle. */
321 bufq_queue(&wd->sc_bufq, bp);
322 s = splbio();
323 octcfstart(wd);
324 splx(s);
325 device_unref(&wd->sc_dev);
326 return;
327
328 bad:
329 bp->b_flags |= B_ERROR;
330 bp->b_resid = bp->b_bcount;
331 done:
332 s = splbio();
333 biodone(bp);
334 splx(s);
335 if (wd != NULL)
336 device_unref(&wd->sc_dev);
337 }
338
339 /*
340 * Queue a drive for I/O.
341 */
342 void
octcfstart(void * arg)343 octcfstart(void *arg)
344 {
345 struct octcf_softc *wd = arg;
346 struct buf *bp;
347
348 OCTCFDEBUG_PRINT(("%s %s\n", __func__, wd->sc_dev.dv_xname),
349 DEBUG_XFERS);
350 while ((bp = bufq_dequeue(&wd->sc_bufq)) != NULL) {
351 /* Transfer this buffer now. */
352 _octcfstart(wd, bp);
353 }
354 }
355
356 void
_octcfstart(struct octcf_softc * wd,struct buf * bp)357 _octcfstart(struct octcf_softc *wd, struct buf *bp)
358 {
359 struct disklabel *lp;
360 u_int64_t secno;
361 u_int64_t nsecs;
362
363 lp = wd->sc_dk.dk_label;
364 secno = DL_BLKTOSEC(lp, bp->b_blkno) +
365 DL_GETPOFFSET(&lp->d_partitions[DISKPART(bp->b_dev)]);
366 nsecs = howmany(bp->b_bcount, lp->d_secsize);
367 wd->sc_bp = bp;
368
369 /* Instrumentation. */
370 disk_busy(&wd->sc_dk);
371
372 if (bp->b_flags & B_READ)
373 bp->b_error = octcf_read_sectors(wd, nsecs, secno, bp->b_data);
374 else
375 bp->b_error = octcf_write_sectors(wd, nsecs, secno, bp->b_data);
376
377 octcfdone(wd);
378 }
379
380 void
octcfdone(void * arg)381 octcfdone(void *arg)
382 {
383 struct octcf_softc *wd = arg;
384 struct buf *bp = wd->sc_bp;
385
386 if (bp->b_error == 0)
387 bp->b_resid = 0;
388 else
389 bp->b_flags |= B_ERROR;
390
391 disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid),
392 bp->b_blkno, (bp->b_flags & B_READ));
393 biodone(bp);
394 }
395
396 int
octcfread(dev_t dev,struct uio * uio,int flags)397 octcfread(dev_t dev, struct uio *uio, int flags)
398 {
399
400 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_XFERS);
401 return (physio(octcfstrategy, dev, B_READ, minphys, uio));
402 }
403
404 int
octcfwrite(dev_t dev,struct uio * uio,int flags)405 octcfwrite(dev_t dev, struct uio *uio, int flags)
406 {
407
408 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_XFERS);
409 return (physio(octcfstrategy, dev, B_WRITE, minphys, uio));
410 }
411
412 int
octcfopen(dev_t dev,int flag,int fmt,struct proc * p)413 octcfopen(dev_t dev, int flag, int fmt, struct proc *p)
414 {
415 struct octcf_softc *wd;
416 int unit, part;
417 int error;
418
419 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
420
421 unit = DISKUNIT(dev);
422 wd = octcflookup(unit);
423 if (wd == NULL)
424 return ENXIO;
425
426 /*
427 * If this is the first open of this device, add a reference
428 * to the adapter.
429 */
430 if ((error = disk_lock(&wd->sc_dk)) != 0)
431 goto bad4;
432
433 if (wd->sc_dk.dk_openmask != 0) {
434 /*
435 * If any partition is open, but the disk has been invalidated,
436 * disallow further opens.
437 */
438 if ((wd->sc_flags & OCTCFF_LOADED) == 0) {
439 error = EIO;
440 goto bad3;
441 }
442 } else {
443 if ((wd->sc_flags & OCTCFF_LOADED) == 0) {
444 wd->sc_flags |= OCTCFF_LOADED;
445
446 /* Load the physical device parameters. */
447 octcf_get_params(wd, &wd->sc_params);
448
449 /* Load the partition info if not already loaded. */
450 if (octcfgetdisklabel(dev, wd,
451 wd->sc_dk.dk_label, 0) == EIO) {
452 error = EIO;
453 goto bad;
454 }
455 }
456 }
457
458 part = DISKPART(dev);
459
460 if ((error = disk_openpart(&wd->sc_dk, part, fmt, 1)) != 0)
461 goto bad;
462
463 disk_unlock(&wd->sc_dk);
464 device_unref(&wd->sc_dev);
465 return 0;
466
467 bad:
468 if (wd->sc_dk.dk_openmask == 0) {
469 }
470
471 bad3:
472 disk_unlock(&wd->sc_dk);
473 bad4:
474 device_unref(&wd->sc_dev);
475 return error;
476 }
477
478 int
octcfclose(dev_t dev,int flag,int fmt,struct proc * p)479 octcfclose(dev_t dev, int flag, int fmt, struct proc *p)
480 {
481 struct octcf_softc *wd;
482 int part = DISKPART(dev);
483
484 wd = octcflookup(DISKUNIT(dev));
485 if (wd == NULL)
486 return ENXIO;
487
488 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
489
490 disk_lock_nointr(&wd->sc_dk);
491
492 disk_closepart(&wd->sc_dk, part, fmt);
493
494 disk_unlock(&wd->sc_dk);
495
496 device_unref(&wd->sc_dev);
497 return (0);
498 }
499
500 void
octcfgetdefaultlabel(struct octcf_softc * wd,struct disklabel * lp)501 octcfgetdefaultlabel(struct octcf_softc *wd, struct disklabel *lp)
502 {
503 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
504 bzero(lp, sizeof(struct disklabel));
505
506 lp->d_secsize = DEV_BSIZE;
507 DL_SETDSIZE(lp, wd->sc_capacity);
508 lp->d_ntracks = wd->sc_params.atap_heads;
509 lp->d_nsectors = wd->sc_params.atap_sectors;
510 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
511 lp->d_ncylinders = DL_GETDSIZE(lp) / lp->d_secpercyl;
512 lp->d_type = DTYPE_ESDI;
513 strncpy(lp->d_typename, "ESDI/IDE disk", sizeof lp->d_typename);
514
515 /* XXX - user viscopy() like sd.c */
516 strncpy(lp->d_packname, wd->sc_params.atap_model, sizeof lp->d_packname);
517 lp->d_version = 1;
518
519 lp->d_magic = DISKMAGIC;
520 lp->d_magic2 = DISKMAGIC;
521 lp->d_checksum = dkcksum(lp);
522 }
523
524 /*
525 * Fabricate a default disk label, and try to read the correct one.
526 */
527 int
octcfgetdisklabel(dev_t dev,struct octcf_softc * wd,struct disklabel * lp,int spoofonly)528 octcfgetdisklabel(dev_t dev, struct octcf_softc *wd, struct disklabel *lp,
529 int spoofonly)
530 {
531 int error;
532
533 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
534
535 octcfgetdefaultlabel(wd, lp);
536 error = readdisklabel(DISKLABELDEV(dev), octcfstrategy, lp,
537 spoofonly);
538 return (error);
539 }
540
541 int
octcfioctl(dev_t dev,u_long xfer,caddr_t addr,int flag,struct proc * p)542 octcfioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, struct proc *p)
543 {
544 struct octcf_softc *wd;
545 struct disklabel *lp;
546 int error = 0;
547
548 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
549
550 wd = octcflookup(DISKUNIT(dev));
551 if (wd == NULL)
552 return ENXIO;
553
554 if ((wd->sc_flags & OCTCFF_LOADED) == 0) {
555 error = EIO;
556 goto exit;
557 }
558
559 switch (xfer) {
560 case DIOCRLDINFO:
561 lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK);
562 octcfgetdisklabel(dev, wd, lp, 0);
563 bcopy(lp, wd->sc_dk.dk_label, sizeof(*lp));
564 free(lp, M_TEMP, sizeof(*lp));
565 goto exit;
566
567 case DIOCGPDINFO:
568 octcfgetdisklabel(dev, wd, (struct disklabel *)addr, 1);
569 goto exit;
570
571 case DIOCGDINFO:
572 *(struct disklabel *)addr = *(wd->sc_dk.dk_label);
573 goto exit;
574
575 case DIOCGPART:
576 ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label;
577 ((struct partinfo *)addr)->part =
578 &wd->sc_dk.dk_label->d_partitions[DISKPART(dev)];
579 goto exit;
580
581 case DIOCWDINFO:
582 case DIOCSDINFO:
583 if ((flag & FWRITE) == 0) {
584 error = EBADF;
585 goto exit;
586 }
587
588 if ((error = disk_lock(&wd->sc_dk)) != 0)
589 goto exit;
590
591 error = setdisklabel(wd->sc_dk.dk_label,
592 (struct disklabel *)addr, wd->sc_dk.dk_openmask);
593 if (error == 0) {
594 if (xfer == DIOCWDINFO)
595 error = writedisklabel(DISKLABELDEV(dev),
596 octcfstrategy, wd->sc_dk.dk_label);
597 }
598
599 disk_unlock(&wd->sc_dk);
600 goto exit;
601
602 default:
603 error = ENOTTY;
604 goto exit;
605 }
606
607 #ifdef DIAGNOSTIC
608 panic("octcfioctl: impossible");
609 #endif
610
611 exit:
612 device_unref(&wd->sc_dev);
613 return (error);
614 }
615
616 #ifdef B_FORMAT
617 int
wdformat(struct buf * bp)618 wdformat(struct buf *bp)
619 {
620 bp->b_flags |= B_FORMAT;
621 return octcfstrategy(bp);
622 }
623 #endif
624
625 daddr_t
octcfsize(dev_t dev)626 octcfsize(dev_t dev)
627 {
628 struct octcf_softc *wd;
629 struct disklabel *lp;
630 int part, omask;
631 daddr_t size;
632
633 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
634
635 wd = octcflookup(DISKUNIT(dev));
636 if (wd == NULL)
637 return (-1);
638
639 part = DISKPART(dev);
640 omask = wd->sc_dk.dk_openmask & (1 << part);
641
642 if (omask == 0 && octcfopen(dev, 0, S_IFBLK, NULL) != 0) {
643 size = -1;
644 goto exit;
645 }
646
647 lp = wd->sc_dk.dk_label;
648 size = DL_SECTOBLK(lp, DL_GETPSIZE(&lp->d_partitions[part]));
649 if (omask == 0 && octcfclose(dev, 0, S_IFBLK, NULL) != 0)
650 size = -1;
651
652 exit:
653 device_unref(&wd->sc_dev);
654 return (size);
655 }
656
657 /*
658 * Dump core after a system crash.
659 */
660 int
octcfdump(dev_t dev,daddr_t blkno,caddr_t va,size_t size)661 octcfdump(dev_t dev, daddr_t blkno, caddr_t va, size_t size)
662 {
663 return ENXIO;
664 }
665
666 int
octcf_read_sectors(struct octcf_softc * wd,uint32_t nr_sectors,uint32_t start_sector,void * buf)667 octcf_read_sectors(struct octcf_softc *wd, uint32_t nr_sectors,
668 uint32_t start_sector, void *buf)
669 {
670 uint32_t count;
671 uint16_t *ptr = (uint16_t*)buf;
672 int error;
673 uint8_t status;
674
675 while (nr_sectors--) {
676 while ((status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY)
677 DELAY(OCTCFDELAY);
678 octcf_command(wd, start_sector++, WDCC_READ);
679 error = octcf_wait_busy(wd);
680 if (error != 0)
681 return (error);
682
683 volatile uint16_t dummy;
684 for (count = 0; count < SECTOR_SIZE; count+=2) {
685 uint16_t temp;
686 temp = OCTCF_REG_READ(wd, 0x0);
687 *ptr++ = swap16(temp);
688 if ((count & 0xf) == 0)
689 dummy = OCTCF_REG_READ(wd, wdr_status);
690 }
691 }
692 return (0);
693 }
694
695 int
octcf_write_sectors(struct octcf_softc * wd,uint32_t nr_sectors,uint32_t start_sector,void * buf)696 octcf_write_sectors(struct octcf_softc *wd, uint32_t nr_sectors,
697 uint32_t start_sector, void *buf)
698 {
699 uint32_t count;
700 uint16_t *ptr = (uint16_t*)buf;
701 int error;
702 uint8_t status;
703
704 while (nr_sectors--) {
705 while ((status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY)
706 DELAY(OCTCFDELAY);
707 octcf_command(wd, start_sector++, WDCC_WRITE);
708 if((error = octcf_wait_busy(wd)))
709 return (error);
710
711 volatile uint16_t dummy;
712 for (count = 0; count < SECTOR_SIZE; count+=2) {
713 uint16_t temp = *ptr++;
714 OCTCF_REG_WRITE(wd, 0x0, swap16(temp));
715 if ((count & 0xf) == 0)
716 dummy = OCTCF_REG_READ(wd, wdr_status);
717 }
718 }
719 return (0);
720 }
721
722 void
octcf_command(struct octcf_softc * wd,uint32_t lba,uint8_t cmd)723 octcf_command(struct octcf_softc *wd, uint32_t lba, uint8_t cmd)
724 {
725 OCTCF_REG_WRITE(wd, wdr_seccnt, 1 | ((lba & 0xff) << 8));
726 OCTCF_REG_WRITE(wd, wdr_cyl_lo,
727 ((lba >> 8) & 0xff) | (((lba >> 16) & 0xff) << 8));
728 OCTCF_REG_WRITE(wd, wdr_sdh,
729 (((lba >> 24) & 0xff) | 0xe0) | (cmd << 8));
730 }
731
732 int
octcf_wait_busy(struct octcf_softc * wd)733 octcf_wait_busy(struct octcf_softc *wd)
734 {
735 uint8_t status;
736
737 status = OCTCF_REG_READ(wd, wdr_status)>>8;
738 while ((status & WDCS_BSY) == WDCS_BSY) {
739 if ((status & WDCS_DWF) != 0)
740 return (EIO);
741 DELAY(OCTCFDELAY);
742 status = (uint8_t)(OCTCF_REG_READ(wd, wdr_status)>>8);
743 }
744
745 if ((status & WDCS_DRQ) == 0)
746 return (ENXIO);
747
748 return (0);
749 }
750
751 /* Get the disk's parameters */
752 int
octcf_get_params(struct octcf_softc * wd,struct ataparams * params)753 octcf_get_params(struct octcf_softc *wd, struct ataparams *params)
754 {
755 char *tb;
756 int i;
757 u_int16_t *p;
758 int count;
759 uint8_t status;
760 int error;
761
762 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS);
763
764 tb = malloc(ATAPARAMS_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO);
765 if (tb == NULL)
766 return CMD_AGAIN;
767
768 while ((status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY)
769 DELAY(OCTCFDELAY);
770
771 OCTCF_REG_WRITE(wd, wdr_seccnt, 0);
772 OCTCF_REG_WRITE(wd, wdr_cyl_lo, 0);
773 OCTCF_REG_WRITE(wd, wdr_sdh, 0 | (WDCC_IDENTIFY<<8));
774
775 error = octcf_wait_busy(wd);
776 if (error == 0) {
777 for (count = 0; count < SECTOR_SIZE; count+=2) {
778 uint16_t temp;
779 temp = OCTCF_REG_READ(wd, 0x0);
780
781 /* endianness will be swapped below */
782 tb[count] = (temp & 0xff);
783 tb[count+1] = (temp & 0xff00)>>8;
784 }
785 }
786
787 if (error != 0) {
788 printf("%s: identify failed: %d\n", __func__, error);
789 free(tb, M_DEVBUF, ATAPARAMS_SIZE);
790 return CMD_ERR;
791 } else {
792 /*
793 * All the fields in the params structure are 16-bit
794 * integers except for the ID strings which are char
795 * strings. The 16-bit integers are currently in
796 * memory in little-endian, regardless of architecture.
797 * So, they need to be swapped on big-endian architectures
798 * before they are accessed through the ataparams structure.
799 *
800 * The swaps below avoid touching the char strings.
801 */
802 swap16_multi((u_int16_t *)tb, 10);
803 swap16_multi((u_int16_t *)tb + 20, 3);
804 swap16_multi((u_int16_t *)tb + 47, ATAPARAMS_SIZE / 2 - 47);
805
806 /* Read in parameter block. */
807 bcopy(tb, params, sizeof(struct ataparams));
808
809 /*
810 * Shuffle string byte order.
811 * ATAPI Mitsumi and NEC drives don't need this.
812 */
813 if ((params->atap_config & WDC_CFG_ATAPI_MASK) ==
814 WDC_CFG_ATAPI &&
815 ((params->atap_model[0] == 'N' &&
816 params->atap_model[1] == 'E') ||
817 (params->atap_model[0] == 'F' &&
818 params->atap_model[1] == 'X'))) {
819 free(tb, M_DEVBUF, ATAPARAMS_SIZE);
820 return CMD_OK;
821 }
822 for (i = 0; i < sizeof(params->atap_model); i += 2) {
823 p = (u_short *)(params->atap_model + i);
824 *p = swap16(*p);
825 }
826 for (i = 0; i < sizeof(params->atap_serial); i += 2) {
827 p = (u_short *)(params->atap_serial + i);
828 *p = swap16(*p);
829 }
830 for (i = 0; i < sizeof(params->atap_revision); i += 2) {
831 p = (u_short *)(params->atap_revision + i);
832 *p = swap16(*p);
833 }
834
835 free(tb, M_DEVBUF, ATAPARAMS_SIZE);
836 return CMD_OK;
837 }
838 }
839