This commit was generated by cvs2svn to track changes on a CVS vendor
[binutils-gdb.git] / sim / ppc / hw_disk.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21
22 #ifndef _HW_DISK_C_
23 #define _HW_DISK_C_
24
25 #include "device_table.h"
26
27 #include "pk.h"
28
29 #include <stdio.h>
30
31
32 /* DEVICE
33
34 cdrom - readable block device
35
36 disk - readable block device that should be writeable
37
38 floppy - readable block device that should be writeable
39
40 DESCRIPTION
41
42 Block I/O devices that model the behavour of a fixed or removable
43 disk device.
44
45 Creating an instance of this device with no arguments will provide
46 access to primative read/write operators. If arguments are
47 specified then the disk-label package is used to perform abstract
48 disk I/O. The disk-label package will then use this devices
49 primatives.
50
51 For hardware I/O, this device would normally be attached to a
52 parent `bus' and that bus would use the I/O methods to read and
53 write raw data. The bus might actually be a SCSI or IDE device.
54 It is assumed that the parent bus can take care of DMA.
55
56 PROPERTIES
57
58 reg = <address> (required)
59
60 <address> is parent bus dependant.
61
62 device_type = "block"
63
64 name = "disk" | "cdrom" | "fd"
65
66 file = <file-name> (required)
67
68 The name of the file that contains the disk image.
69
70 */
71
72 typedef struct _hw_disk_device {
73 const char *name;
74 int read_only;
75 unsigned_word size;
76 FILE *image;
77 } hw_disk_device;
78
79 typedef struct _hw_disk_instance {
80 long pos;
81 hw_disk_device *disk;
82 } hw_disk_instance;
83
84
85 static void
86 hw_disk_init_address(device *me)
87 {
88 hw_disk_device *disk = device_data(me);
89 generic_device_init_address(me);
90 if (disk->image != NULL)
91 fclose(disk->image);
92 disk->name = device_find_string_property(me, "file");
93 if (strcmp(device_name(me), "disk") == 0) {
94 disk->read_only = 0;
95 disk->image = fopen(disk->name, "r+");
96 }
97 else {
98 disk->read_only = 1;
99 disk->image = fopen(disk->name, "r");
100 }
101 if (disk->image == NULL) {
102 perror(device_name(me));
103 device_error(me, "open %s failed\n", disk->name);
104 }
105 }
106
107 static unsigned
108 hw_disk_io_read_buffer(device *me,
109 void *dest,
110 int space,
111 unsigned_word addr,
112 unsigned nr_bytes,
113 cpu *processor,
114 unsigned_word cia)
115 {
116 hw_disk_device *disk = device_data(me);
117 if (nr_bytes == 0)
118 return 0;
119 if (addr + nr_bytes > disk->size)
120 return 0;
121 if (fseek(disk->image, addr, SEEK_SET) < 0)
122 return 0;
123 if (fread(dest, nr_bytes, 1, disk->image) != 1)
124 return 0;
125 return nr_bytes;
126 }
127
128
129 static unsigned
130 hw_disk_io_write_buffer(device *me,
131 const void *source,
132 int space,
133 unsigned_word addr,
134 unsigned nr_bytes,
135 cpu *processor,
136 unsigned_word cia)
137 {
138 hw_disk_device *disk = device_data(me);
139 if (disk->read_only)
140 return 0;
141 if (nr_bytes == 0)
142 return 0;
143 if (addr + nr_bytes > disk->size)
144 return 0;
145 if (fseek(disk->image, addr, SEEK_SET) < 0)
146 return 0;
147 if (fwrite(source, nr_bytes, 1, disk->image) != 1)
148 return 0;
149 return nr_bytes;
150 }
151
152
153 /* instances of the hw_disk device */
154
155 static void
156 hw_disk_instance_delete(device_instance *instance)
157 {
158 hw_disk_instance *data = device_instance_data(instance);
159 zfree(data);
160 }
161
162 static int
163 hw_disk_instance_read(device_instance *instance,
164 void *buf,
165 unsigned_word len)
166 {
167 hw_disk_instance *data = device_instance_data(instance);
168 if (fseek(data->disk->image, data->pos, SEEK_SET) < 0)
169 return -1;
170 if (fread(buf, len, 1, data->disk->image) != 1)
171 return -1;
172 data->pos = ftell(data->disk->image);
173 return len;
174 }
175
176 static int
177 hw_disk_instance_write(device_instance *instance,
178 const void *buf,
179 unsigned_word len)
180 {
181 hw_disk_instance *data = device_instance_data(instance);
182 if (data->disk->read_only)
183 return -1;
184 if (fseek(data->disk->image, data->pos, SEEK_SET) < 0)
185 return -1;
186 if (fwrite(buf, len, 1, data->disk->image) != 1)
187 return -1;
188 data->pos = ftell(data->disk->image);
189 return len;
190 }
191
192 static int
193 hw_disk_instance_seek(device_instance *instance,
194 unsigned_word pos_hi,
195 unsigned_word pos_lo)
196 {
197 hw_disk_instance *data = device_instance_data(instance);
198 data->pos = pos_lo;
199 return 0;
200 }
201
202 static const device_instance_callbacks hw_disk_instance_callbacks = {
203 hw_disk_instance_delete,
204 hw_disk_instance_read,
205 hw_disk_instance_write,
206 hw_disk_instance_seek,
207 };
208
209 static device_instance *
210 hw_disk_create_instance(device *me,
211 const char *path,
212 const char *args)
213 {
214 device_instance *disk_instance;
215 hw_disk_device *disk = device_data(me);
216 hw_disk_instance *data = ZALLOC(hw_disk_instance);
217 data->disk = disk;
218 data->pos = 0;
219 disk_instance = device_create_instance_from(me, NULL,
220 data,
221 path, args,
222 &hw_disk_instance_callbacks);
223 return pk_disklabel_create_instance(disk_instance, args);
224 }
225
226 static device_callbacks const hw_disk_callbacks = {
227 { hw_disk_init_address, NULL },
228 { NULL, }, /* address */
229 { hw_disk_io_read_buffer,
230 hw_disk_io_write_buffer, },
231 { NULL, }, /* DMA */
232 { NULL, }, /* interrupt */
233 { NULL, }, /* unit */
234 hw_disk_create_instance,
235 };
236
237
238 static void *
239 hw_disk_create(const char *name,
240 const device_unit *unit_address,
241 const char *args,
242 device *parent)
243 {
244 /* create the descriptor */
245 hw_disk_device *hw_disk = ZALLOC(hw_disk_device);
246 return hw_disk;
247 }
248
249
250 const device_descriptor hw_disk_device_descriptor[] = {
251 { "disk", hw_disk_create, &hw_disk_callbacks },
252 { NULL },
253 };
254
255 #endif /* _HW_DISK_C_ */