1*3eb244d8Sjoerg /* $NetBSD: riscosdisk.c,v 1.4 2011/07/17 20:54:35 joerg Exp $ */
246dbb0f2Sreinoud
346dbb0f2Sreinoud /*-
4bc24b5d8Sbjh21 * Copyright (c) 2001, 2006 Ben Harris
546dbb0f2Sreinoud * All rights reserved.
646dbb0f2Sreinoud *
746dbb0f2Sreinoud * Redistribution and use in source and binary forms, with or without
846dbb0f2Sreinoud * modification, are permitted provided that the following conditions
946dbb0f2Sreinoud * are met:
1046dbb0f2Sreinoud * 1. Redistributions of source code must retain the above copyright
1146dbb0f2Sreinoud * notice, this list of conditions and the following disclaimer.
1246dbb0f2Sreinoud * 2. Redistributions in binary form must reproduce the above copyright
1346dbb0f2Sreinoud * notice, this list of conditions and the following disclaimer in the
1446dbb0f2Sreinoud * documentation and/or other materials provided with the distribution.
1546dbb0f2Sreinoud * 3. The name of the author may not be used to endorse or promote products
1646dbb0f2Sreinoud * derived from this software without specific prior written permission.
1746dbb0f2Sreinoud *
1846dbb0f2Sreinoud * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1946dbb0f2Sreinoud * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2046dbb0f2Sreinoud * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2146dbb0f2Sreinoud * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2246dbb0f2Sreinoud * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2346dbb0f2Sreinoud * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2446dbb0f2Sreinoud * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2546dbb0f2Sreinoud * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2646dbb0f2Sreinoud * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2746dbb0f2Sreinoud * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2846dbb0f2Sreinoud */
2946dbb0f2Sreinoud
30bc24b5d8Sbjh21 #include <sys/types.h>
31bc24b5d8Sbjh21 #include <sys/param.h>
32bc24b5d8Sbjh21 #include <sys/disklabel.h>
3346dbb0f2Sreinoud #include <lib/libsa/stand.h>
3446dbb0f2Sreinoud #include <riscoscalls.h>
35bc24b5d8Sbjh21 #include <riscosdisk.h>
36bc24b5d8Sbjh21 #include <riscospart.h>
3746dbb0f2Sreinoud
3846dbb0f2Sreinoud struct riscosdisk {
39bc24b5d8Sbjh21 void *privword;
4046dbb0f2Sreinoud int drive;
41bc24b5d8Sbjh21 daddr_t boff;
4246dbb0f2Sreinoud };
4346dbb0f2Sreinoud
44bc24b5d8Sbjh21 static void *
rodisk_getprivateword(char const * fsname)45bc24b5d8Sbjh21 rodisk_getprivateword(char const *fsname)
46bc24b5d8Sbjh21 {
47bc24b5d8Sbjh21 void *privword;
48bc24b5d8Sbjh21 char module[20];
49bc24b5d8Sbjh21 os_error *err;
50bc24b5d8Sbjh21
51bc24b5d8Sbjh21 /* XXX The %c dance is because libsa printf can't do %% */
52bc24b5d8Sbjh21 snprintf(module, sizeof(module), "FileCore%c%s", '%', fsname);
53bc24b5d8Sbjh21 err = xosmodule_lookup(module, NULL, NULL, NULL, &privword, NULL);
54bc24b5d8Sbjh21 if (err != NULL)
55bc24b5d8Sbjh21 return NULL;
56bc24b5d8Sbjh21 return privword;
57bc24b5d8Sbjh21 }
58bc24b5d8Sbjh21
5946dbb0f2Sreinoud int
rodisk_open(struct open_file * f,...)60bc24b5d8Sbjh21 rodisk_open(struct open_file *f, ... /* char const *fsname, int drive,
61bc24b5d8Sbjh21 int partition */)
6246dbb0f2Sreinoud {
6346dbb0f2Sreinoud va_list ap;
64bc24b5d8Sbjh21 struct disklabel dl;
6546dbb0f2Sreinoud char const *fsname;
66bc24b5d8Sbjh21 int drive, partition, nfd, nhd, err;
6746dbb0f2Sreinoud struct riscosdisk *rd;
68bc24b5d8Sbjh21 void *privword;
6946dbb0f2Sreinoud
7046dbb0f2Sreinoud va_start(ap, f);
7146dbb0f2Sreinoud fsname = va_arg(ap, char const *);
7246dbb0f2Sreinoud drive = va_arg(ap, int);
73bc24b5d8Sbjh21 partition = va_arg(ap, int);
7446dbb0f2Sreinoud va_end(ap);
7546dbb0f2Sreinoud
76bc24b5d8Sbjh21 if ((privword = rodisk_getprivateword(fsname)) == NULL)
77bc24b5d8Sbjh21 return ECTLR;
78bc24b5d8Sbjh21 if (xfilecore_drives(&privword, NULL, &nfd, &nhd) != NULL)
79bc24b5d8Sbjh21 return ECTLR;
80bc24b5d8Sbjh21 if (drive < 0 ||
81bc24b5d8Sbjh21 (drive < 4 && drive >= nfd) ||
82bc24b5d8Sbjh21 drive >= nhd + 4)
83bc24b5d8Sbjh21 return EUNIT;
8446dbb0f2Sreinoud
85bc24b5d8Sbjh21 rd = alloc(sizeof(*rd));
86bc24b5d8Sbjh21 rd->privword = privword;
87bc24b5d8Sbjh21 rd->drive = drive;
88bc24b5d8Sbjh21 rd->boff = 0;
89bc24b5d8Sbjh21 f->f_devdata = rd;
90bc24b5d8Sbjh21 if (partition != RAW_PART) {
91bc24b5d8Sbjh21 err = getdisklabel_acorn(f, &dl);
92bc24b5d8Sbjh21 if (err != 0) {
93bc24b5d8Sbjh21 dealloc(rd, sizeof(*rd));
94bc24b5d8Sbjh21 return err;
95bc24b5d8Sbjh21 }
96bc24b5d8Sbjh21 if (partition >= dl.d_npartitions ||
97bc24b5d8Sbjh21 dl.d_partitions[partition].p_size == 0) {
98bc24b5d8Sbjh21 dealloc(rd, sizeof(*rd));
99bc24b5d8Sbjh21 return EPART;
100bc24b5d8Sbjh21 }
101bc24b5d8Sbjh21 rd->boff = dl.d_partitions[partition].p_offset;
102bc24b5d8Sbjh21 }
103bc24b5d8Sbjh21 return 0;
104bc24b5d8Sbjh21 }
10546dbb0f2Sreinoud
106bc24b5d8Sbjh21 int
rodisk_close(struct open_file * f)107bc24b5d8Sbjh21 rodisk_close(struct open_file *f)
108bc24b5d8Sbjh21 {
109bc24b5d8Sbjh21 struct riscosdisk *rd = f->f_devdata;
11046dbb0f2Sreinoud
111bc24b5d8Sbjh21 dealloc(rd, sizeof *rd);
112bc24b5d8Sbjh21 return 0;
113bc24b5d8Sbjh21 }
11446dbb0f2Sreinoud
115bc24b5d8Sbjh21 int
rodisk_strategy(void * devdata,int flag,daddr_t dblk,size_t size,void * buf,size_t * rsize)116bc24b5d8Sbjh21 rodisk_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
117bc24b5d8Sbjh21 void *buf, size_t *rsize)
118bc24b5d8Sbjh21 {
119bc24b5d8Sbjh21 struct riscosdisk *rd = devdata;
120bc24b5d8Sbjh21 size_t resid;
121bc24b5d8Sbjh21 uint32_t daddr, ndaddr;
122bc24b5d8Sbjh21 void *nbuf;
123bc24b5d8Sbjh21 os_error *err;
124bc24b5d8Sbjh21
125bc24b5d8Sbjh21 if (flag != F_READ)
126bc24b5d8Sbjh21 return EROFS;
127bc24b5d8Sbjh21
128bc24b5d8Sbjh21 dblk += rd->boff;
129bc24b5d8Sbjh21
130bc24b5d8Sbjh21 if (rsize) *rsize = 0;
131bc24b5d8Sbjh21 if (dblk < 1 << (29 - DEV_BSHIFT)) {
132bc24b5d8Sbjh21 daddr = (dblk * DEV_BSIZE) | (rd->drive << 29);
133bc24b5d8Sbjh21 if ((err = xfilecorediscop_read_sectors(0, daddr, buf, size,
134bc24b5d8Sbjh21 &rd->privword, &ndaddr, &nbuf, &resid)) != NULL)
135bc24b5d8Sbjh21 goto eio;
136bc24b5d8Sbjh21 } else if (dblk < 1 << 29) {
137bc24b5d8Sbjh21 daddr = dblk | (rd->drive << 29);
138bc24b5d8Sbjh21 if ((err = xfilecoresectorop_read_sectors(0, daddr, buf, size,
139bc24b5d8Sbjh21 &rd->privword, &ndaddr, &nbuf, &resid)) != NULL)
140bc24b5d8Sbjh21 goto eio;
141bc24b5d8Sbjh21 } else if (dblk < 1LL << (64 - DEV_BSHIFT)){
142bc24b5d8Sbjh21 struct filecore_daddr64 daddr64;
143bc24b5d8Sbjh21 daddr64.drive = rd->drive;
144bc24b5d8Sbjh21 daddr64.daddr = dblk * DEV_BSIZE;
145bc24b5d8Sbjh21 if ((err = xfilecorediscop64_read_sectors(0, &daddr64, buf,
146bc24b5d8Sbjh21 size, NULL, &rd->privword, &ndaddr, &nbuf, &resid)) !=
147bc24b5d8Sbjh21 NULL)
148bc24b5d8Sbjh21 goto eio;
149bc24b5d8Sbjh21 } else
150bc24b5d8Sbjh21 return EIO;
151bc24b5d8Sbjh21 if (rsize)
152bc24b5d8Sbjh21 *rsize = size - resid;
153bc24b5d8Sbjh21 return 0;
154bc24b5d8Sbjh21 eio:
155bc24b5d8Sbjh21 printf("Error: %s\n", err->errmess);
156bc24b5d8Sbjh21 return EIO;
157bc24b5d8Sbjh21 }
158