1 /*        $NetBSD: iris_disk.c,v 1.1 2019/01/12 16:44:47 tsutsui Exp $          */
2 
3 /*
4  * Copyright (c) 2018 Naruaki Etomi
5  * 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) 1988 University of Utah.
30  * Copyright (c) 1990, 1993
31  *        The Regents of the University of California.  All rights reserved.
32  *
33  * This code is derived from software contributed to Berkeley by
34  * Van Jacobson of Lawrence Berkeley Laboratory and the Systems
35  * Programming Group of the University of Utah Computer Science Department.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  * 3. Neither the name of the University nor the names of its contributors
46  *    may be used to endorse or promote products derived from this software
47  *    without specific prior written permission.
48  *
49  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59  * SUCH DAMAGE.
60  *
61  * from: Utah $Hdr: sd.c 1.9 92/12/21$
62  *
63  *        @(#)sd.c  8.1 (Berkeley) 6/10/93
64  */
65 
66 /*
67  * Silicon Graphics "IRIS" series MIPS processors machine bootloader.
68  * Disk I/O API routine.
69  * Most of the following was adapted from /sys/arch/hp300/stand/common/sd.c.
70  *        NetBSD: sd.c,v 1.11 2011/07/17 20:54:40 joerg Exp
71  */
72 
73 #include <lib/libsa/stand.h>
74 
75 #include <sys/param.h>
76 #include <sys/disklabel.h>
77 
78 #ifndef   INDIGO_R3K_MODE
79 #include <dev/arcbios/arcbios.h>
80 #endif
81 
82 #include "disk.h"
83 
84 #include "iris_machdep.h"
85 #include "iris_scsivar.h"
86 
87 struct    disk_softc {
88           int       sc_part;            /* disk partition number */
89           char      sc_retry;
90           char      sc_alive;
91           short     sc_blkshift;
92           struct    disklabel sc_label; /* disk label for this disk */
93 };
94 
95 static int diskinit(struct disk_softc *);
96 
97 #define DISKRETRY  2
98 
99 int
diskstrategy(void * devdata,int rw,daddr_t bn,size_t reqcnt,void * addr,size_t * cnt)100 diskstrategy(void *devdata, int rw, daddr_t bn, size_t reqcnt, void *addr,
101     size_t *cnt)
102 {
103           struct disk_softc *sc;
104           struct disklabel *lp;
105           uint8_t *buf;
106           daddr_t blk;
107           u_int nblk;
108           int stat;
109 
110           sc = devdata;
111 
112           buf = addr;
113           lp = &sc->sc_label;
114           blk = bn + (lp->d_partitions[sc->sc_part].p_offset >> sc->sc_blkshift);
115           nblk = reqcnt >> sc->sc_blkshift;
116 
117           sc->sc_retry = 0;
118 
119  retry:
120           stat = scsi_read(buf, reqcnt, blk, nblk);
121 
122           if (stat) {
123                     DELAY(1000000);
124                     if (++sc->sc_retry > DISKRETRY) {
125                               return EIO;
126                     }
127                     printf("diskstrategy retry\n");
128                     goto retry;
129           }
130 
131           *cnt = reqcnt;
132 
133           return 0;
134 }
135 
136 static int
diskinit(struct disk_softc * sc)137 diskinit(struct disk_softc *sc)
138 {
139           uint8_t capbuf[2];
140 
141           uint8_t stat;
142 
143           stat = scsi_test_unit_rdy();
144 
145           if (stat != 0) {
146                     /* drive may be doing RTZ - wait a bit */
147                     DELAY(1000000);
148                     stat = scsi_test_unit_rdy();
149 
150                     if (stat != 0) {
151                               printf("diskinit abort!\n");
152                               printf("Boot failed!  Halting...\n");
153                               reboot();
154                     }
155           }
156 
157           /*
158            * try to get the drive block size.
159            */
160           capbuf[0] = 0;
161           capbuf[1] = 0;
162 
163           stat = scsi_read_capacity((uint8_t *)capbuf, sizeof(capbuf));
164 
165           if (stat == 0) {
166                     if (capbuf[1] > DEV_BSIZE)
167                               for (; capbuf[1] > DEV_BSIZE; capbuf[1] >>= 1)
168                                         ++sc->sc_blkshift;
169           }
170 
171           sc->sc_alive = 1;
172           return 1;
173 }
174 
175 int
diskopen(struct open_file * f,...)176 diskopen(struct open_file *f, ...)
177 {
178           struct disk_softc *sc;
179           struct disklabel *lp;
180           size_t cnt;
181           char *msg, buf[DEV_BSIZE];
182           int error;
183 
184           cnt = 0;
185 
186           sc = alloc(sizeof(struct disk_softc));
187           memset(sc, 0, sizeof(struct disk_softc));
188           f->f_devdata = (void *)sc;
189 
190           sc->sc_part = scsi_part;
191 
192           if (sc->sc_alive == 0) {
193                     if (diskinit(sc) == 0)
194                               return ENXIO;
195           }
196 
197           /* try to read disk label and partition table information */
198           lp = &sc->sc_label;
199           lp->d_secsize = DEV_BSIZE;
200           lp->d_secpercyl = 1;
201           lp->d_npartitions = MAXPARTITIONS;
202           lp->d_partitions[scsi_part].p_offset = 0;
203           lp->d_partitions[scsi_part].p_size = 0x7fffffff;
204 
205           error = diskstrategy(sc, F_READ, (daddr_t)LABELSECTOR, DEV_BSIZE, buf,
206               &cnt);
207 
208           if (error || cnt != DEV_BSIZE) {
209                     printf("diskstrategy error...\n");
210                     dealloc(sc, sizeof(struct disk_softc));
211                     return ENXIO;
212           }
213 
214           msg = getdisklabel(buf, lp);
215 
216           if (msg) {
217                     /* If no label, just assume 0 and return */
218                     printf("No disklabel...\n");
219                     reboot();
220           }
221 
222           return 0;
223 }
224 
225 int
diskclose(struct open_file * f)226 diskclose(struct open_file *f)
227 {
228           struct disk_softc *sc = f->f_devdata;
229 
230           dealloc(sc, sizeof *sc);
231           f->f_devdata = NULL;
232 
233           return 0;
234 }
235