xref: /netbsd-src/sys/arch/acorn32/stand/lib/riscosdisk.c (revision 3eb244d801190b3a7d8cd42193c38a77c1dbae1a)
1 /*	$NetBSD: riscosdisk.c,v 1.4 2011/07/17 20:54:35 joerg Exp $	*/
2 
3 /*-
4  * Copyright (c) 2001, 2006 Ben Harris
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  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <sys/types.h>
31 #include <sys/param.h>
32 #include <sys/disklabel.h>
33 #include <lib/libsa/stand.h>
34 #include <riscoscalls.h>
35 #include <riscosdisk.h>
36 #include <riscospart.h>
37 
38 struct riscosdisk {
39 	void	*privword;
40 	int	drive;
41 	daddr_t	boff;
42 };
43 
44 static void *
rodisk_getprivateword(char const * fsname)45 rodisk_getprivateword(char const *fsname)
46 {
47 	void *privword;
48 	char module[20];
49 	os_error *err;
50 
51 	/* XXX The %c dance is because libsa printf can't do %% */
52 	snprintf(module, sizeof(module), "FileCore%c%s", '%', fsname);
53 	err = xosmodule_lookup(module, NULL, NULL, NULL, &privword, NULL);
54 	if (err != NULL)
55 		return NULL;
56 	return privword;
57 }
58 
59 int
rodisk_open(struct open_file * f,...)60 rodisk_open(struct open_file *f, ... /* char const *fsname, int drive,
61     int partition */)
62 {
63 	va_list ap;
64 	struct disklabel dl;
65 	char const *fsname;
66 	int drive, partition, nfd, nhd, err;
67 	struct riscosdisk *rd;
68 	void *privword;
69 
70 	va_start(ap, f);
71 	fsname = va_arg(ap, char const *);
72 	drive = va_arg(ap, int);
73 	partition = va_arg(ap, int);
74 	va_end(ap);
75 
76 	if ((privword = rodisk_getprivateword(fsname)) == NULL)
77 		return ECTLR;
78 	if (xfilecore_drives(&privword, NULL, &nfd, &nhd) != NULL)
79 		return ECTLR;
80 	if (drive < 0 ||
81 	    (drive < 4 && drive >= nfd) ||
82 	    drive >= nhd + 4)
83 		return EUNIT;
84 
85 	rd = alloc(sizeof(*rd));
86 	rd->privword = privword;
87 	rd->drive = drive;
88 	rd->boff = 0;
89 	f->f_devdata = rd;
90 	if (partition != RAW_PART) {
91 		err = getdisklabel_acorn(f, &dl);
92 		if (err != 0) {
93 			dealloc(rd, sizeof(*rd));
94 			return err;
95 		}
96 		if (partition >= dl.d_npartitions ||
97 		    dl.d_partitions[partition].p_size == 0) {
98 			dealloc(rd, sizeof(*rd));
99 			return EPART;
100 		}
101 		rd->boff = dl.d_partitions[partition].p_offset;
102 	}
103 	return 0;
104 }
105 
106 int
rodisk_close(struct open_file * f)107 rodisk_close(struct open_file *f)
108 {
109 	struct riscosdisk *rd = f->f_devdata;
110 
111 	dealloc(rd, sizeof *rd);
112 	return 0;
113 }
114 
115 int
rodisk_strategy(void * devdata,int flag,daddr_t dblk,size_t size,void * buf,size_t * rsize)116 rodisk_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
117     void *buf, size_t *rsize)
118 {
119 	struct riscosdisk *rd = devdata;
120 	size_t resid;
121 	uint32_t daddr, ndaddr;
122 	void *nbuf;
123 	os_error *err;
124 
125 	if (flag != F_READ)
126 		return EROFS;
127 
128 	dblk += rd->boff;
129 
130 	if (rsize) *rsize = 0;
131 	if (dblk < 1 << (29 - DEV_BSHIFT)) {
132 		daddr = (dblk * DEV_BSIZE) | (rd->drive << 29);
133 		if ((err = xfilecorediscop_read_sectors(0, daddr, buf, size,
134 		    &rd->privword, &ndaddr, &nbuf, &resid)) != NULL)
135 			goto eio;
136 	} else if (dblk < 1 << 29) {
137 		daddr = dblk | (rd->drive << 29);
138 		if ((err = xfilecoresectorop_read_sectors(0, daddr, buf, size,
139 		    &rd->privword, &ndaddr, &nbuf, &resid)) != NULL)
140 			goto eio;
141 	} else if (dblk < 1LL << (64 - DEV_BSHIFT)){
142 		struct filecore_daddr64 daddr64;
143 		daddr64.drive = rd->drive;
144 		daddr64.daddr = dblk * DEV_BSIZE;
145 		if ((err = xfilecorediscop64_read_sectors(0, &daddr64, buf,
146 		    size, NULL, &rd->privword, &ndaddr, &nbuf, &resid)) !=
147 		    NULL)
148 			goto eio;
149 	} else
150 		return EIO;
151 	if (rsize)
152 		*rsize = size - resid;
153 	return 0;
154 eio:
155 	printf("Error: %s\n", err->errmess);
156 	return EIO;
157 }
158