OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [sim/] [ppc/] [hw_disk.c] - Blame information for rev 438

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 24 jeremybenn
/*  This file is part of the program psim.
2
 
3
    Copyright (C) 1994-1997, 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
#ifdef HAVE_UNISTD_H
32
#include <unistd.h>
33
#endif
34
 
35
#ifndef SEEK_SET
36
#define SEEK_SET 0
37
#endif
38
 
39
/* DEVICE
40
 
41
 
42
   cdrom - read-only removable mass storage device
43
 
44
   disk - mass storage device
45
 
46
   floppy - removable mass storage device
47
 
48
 
49
   DESCRIPTION
50
 
51
 
52
   Mass storage devices such as a hard-disk or cdrom-drive are not
53
   normally directly connected to the processor.  Instead, these
54
   devices are attached to a logical bus, such as SCSI or IDE, and
55
   then a controller of that bus is made accessible to the processor.
56
 
57
   Reflecting this, within a device tree, mass storage devices such as
58
   a <<cdrom>>, <<disk>> or <<floppy>> are created as children of of a
59
   logical bus controller node (such as a SCSI or IDE interface).
60
   That controller, in turn, would be made the child of a physical bus
61
   node that is directly accessible to the processor.
62
 
63
   The above mass storage devices provide two interfaces - a logical
64
   and a physical.
65
 
66
   At the physical level the <<device_io_...>> functions can be used
67
   perform reads and writes of the raw media.  The address being
68
   interpreted as an offset from the start of the disk.
69
 
70
   At the logical level, it is possible to create an instance of the
71
   disk that provides access to any of the physical media, a disk
72
   partition, or even a file within a partition.  The <<disk-label>>
73
   package, which implements this functionality, is described
74
   elsewhere.  Both the Open Firmware and Moto BUG rom emulations
75
   support this interface.
76
 
77
   Block devices such as the <<floppy>> and <<cdrom>> have removable
78
   media.  At the programmer level, the media can be changed using the
79
   <<change_media>> ioctl.  From within GDB, a <<change-media>>
80
   operation can be initated by using the command.
81
 
82
   |    (gdb)  sim
83
 
84
 
85
   PROPERTIES
86
 
87
 
88
   file = <file-name>  (required)
89
 
90
   The name of the file that contains an image of the disk.  For
91
   <<disk>> and <<floppy>> devices, the image will be opened for both
92
   reading and writing.  Multiple image files may be specified, the
93
   second and later files being opened when <<change-media>> (with a
94
   NULL file name) being specified.
95
 
96
 
97
   block-size = <nr-bytes>  (optional)
98
 
99
   The value is returned by the block-size method.  The default value
100
   is 512 bytes.
101
 
102
 
103
   max-transfer = <nr-bytes>  (optional)
104
 
105
   The value is returned by the max-transfer method. The default value
106
   is 512 bytes.
107
 
108
 
109
   #blocks = <nr-blocks>  (optional)
110
 
111
   The value is returned by the #blocks method.  If no value is
112
   present then -1 is returned.
113
 
114
 
115
   read-only = <anything>  (optional)
116
 
117
   If this property is present, the disk file image is always opened
118
   read-only.
119
 
120
   EXAMPLES
121
 
122
 
123
   Enable tracing
124
 
125
   | $  psim -t 'disk-device' \
126
 
127
 
128
   Add a CDROM and disk to an IDE bus.  Specify the host operating
129
   system's cd drive as the CD-ROM image.
130
 
131
   |    -o '/pci/ide/disk@0/file "disk-image' \
132
   |    -o '/pci/ide/cdrom@1/file "/dev/cd0a' \
133
 
134
 
135
   As part of the code implementing a logical bus device (for instance
136
   the IDE controller), locate the CDROM device and then read block
137
   47.
138
 
139
   |  device *cdrom = device_tree_find_device(me, "cdrom");
140
   |  char block[512];
141
   |  device_io_read_buffer(cdrom, buf, 0,
142
                            0, 47 * sizeof(block), // space, address
143
                            sizeof(block), NULL, 0);
144
 
145
 
146
   Use the device instance interface to read block 47 of the file
147
   called <<netbsd.elf>> on the disks default partition.  Similar code
148
   would be used in an operating systems pre-boot loader.
149
 
150
   |  device_instance *netbsd =
151
   |    device_create_instance(root, "/pci/ide/disk:,\netbsd.elf");
152
   |  char block[512];
153
   |  device_instance_seek(netbsd,  0, 47 * sizeof(block));
154
   |  device_instance_read(netbsd, block, sizeof(block));
155
 
156
 
157
   BUGS
158
 
159
 
160
   The block device specification includes mechanisms for determining
161
   the physical device characteristics - such as the disks size.
162
   Currently this mechanism is not implemented.
163
 
164
   The functionality of this device (in particular the device instance
165
   interface) depends on the implementation of <<disk-label>> package.
166
   That package may not be fully implemented.
167
 
168
   The disk does not know its size.  Hence it relies on the failure of
169
   fread(), fwrite() and fseek() calls to detect errors.
170
 
171
   The disk size is limited by the addressable range covered by
172
   unsigned_word (addr).  An extension would be to instead use the
173
   concatenated value space:addr.
174
 
175
   The method #blocks should `stat' the disk to determine the number
176
   of blocks if there is no #blocks property.
177
 
178
   It would appear that OpenFirmware does not define a client call for
179
   changing (ejecting) the media of a device.
180
 
181
   */
182
 
183
typedef struct _hw_disk_device {
184
  int name_index;
185
  int nr_names;
186
  char *name;
187
  int read_only;
188
  /*  unsigned_word size; */
189
  FILE *image;
190
} hw_disk_device;
191
 
192
typedef struct _hw_disk_instance {
193
  unsigned_word pos;
194
  hw_disk_device *disk;
195
} hw_disk_instance;
196
 
197
 
198
static void
199
open_disk_image(device *me,
200
                hw_disk_device *disk,
201
                const char *name)
202
{
203
  if (disk->image != NULL)
204
    fclose(disk->image);
205
  if (disk->name != NULL)
206
    zfree(disk->name);
207
  disk->name = strdup(name);
208
  disk->image = fopen(disk->name, disk->read_only ? "r" : "r+");
209
  if (disk->image == NULL) {
210
    perror(device_name(me));
211
    device_error(me, "open %s failed\n", disk->name);
212
  }
213
 
214
  DTRACE(disk, ("image %s (%s)\n",
215
                disk->name,
216
                (disk->read_only ? "read-only" : "read-write")));
217
}
218
 
219
static void
220
hw_disk_init_address(device *me)
221
{
222
  hw_disk_device *disk = device_data(me);
223
  unsigned_word address;
224
  int space;
225
  const char *name;
226
 
227
  /* attach to the parent. Since the bus is logical, attach using just
228
     the unit-address (size must be zero) */
229
  device_address_to_attach_address(device_parent(me), device_unit_address(me),
230
                                   &space, &address, me);
231
  device_attach_address(device_parent(me), attach_callback,
232
                        space, address, 0/*size*/, access_read_write_exec,
233
                        me);
234
 
235
  /* Tell the world we are a disk.  */
236
  device_add_string_property(me, "device_type", "block");
237
 
238
  /* get the name of the file specifying the disk image */
239
  disk->name_index = 0;
240
  disk->nr_names = device_find_string_array_property(me, "file",
241
                                                     disk->name_index, &name);
242
  if (!disk->nr_names)
243
    device_error(me, "invalid file property");
244
 
245
  /* is it a RO device? */
246
  disk->read_only =
247
    (strcmp(device_name(me), "disk") != 0
248
     && strcmp(device_name(me), "floppy") != 0
249
     && device_find_property(me, "read-only") == NULL);
250
 
251
  /* now open it */
252
  open_disk_image(me, disk, name);
253
}
254
 
255
static int
256
hw_disk_ioctl(device *me,
257
              cpu *processor,
258
              unsigned_word cia,
259
              device_ioctl_request request,
260
              va_list ap)
261
{
262
  switch (request) {
263
  case device_ioctl_change_media:
264
    {
265
      hw_disk_device *disk = device_data(me);
266
      const char *name = va_arg(ap, const char *);
267
      if (name != NULL) {
268
        disk->name_index = -1;
269
      }
270
      else {
271
        disk->name_index = (disk->name_index + 1) % disk->nr_names;
272
        if (!device_find_string_array_property(me, "file",
273
                                               disk->name_index, &name))
274
          device_error(me, "invalid file property");
275
      }
276
      open_disk_image(me, disk, name);
277
    }
278
    break;
279
  default:
280
    device_error(me, "insupported ioctl request");
281
    break;
282
  }
283
  return 0;
284
}
285
 
286
 
287
 
288
 
289
 
290
static unsigned
291
hw_disk_io_read_buffer(device *me,
292
                       void *dest,
293
                       int space,
294
                       unsigned_word addr,
295
                       unsigned nr_bytes,
296
                       cpu *processor,
297
                       unsigned_word cia)
298
{
299
  hw_disk_device *disk = device_data(me);
300
  unsigned nr_bytes_read;
301
  if (space != 0)
302
    device_error(me, "read - extended disk addressing unimplemented");
303
  if (nr_bytes == 0)
304
    nr_bytes_read = 0;
305
  else if (fseek(disk->image, addr, SEEK_SET) < 0)
306
    nr_bytes_read = 0;
307
  else if (fread(dest, nr_bytes, 1, disk->image) != 1)
308
    nr_bytes_read = 0;
309
  else
310
    nr_bytes_read = nr_bytes;
311
  DTRACE(disk, ("io-read - address 0x%lx, nr-bytes-read %d, requested %d\n",
312
                (unsigned long) addr, (int)nr_bytes_read, (int)nr_bytes));
313
  return nr_bytes_read;
314
}
315
 
316
 
317
static unsigned
318
hw_disk_io_write_buffer(device *me,
319
                        const void *source,
320
                        int space,
321
                        unsigned_word addr,
322
                        unsigned nr_bytes,
323
                        cpu *processor,
324
                        unsigned_word cia)
325
{
326
  hw_disk_device *disk = device_data(me);
327
  unsigned nr_bytes_written;
328
  if (space != 0)
329
    device_error(me, "write - extended disk addressing unimplemented");
330
  if (disk->read_only)
331
    nr_bytes_written = 0;
332
  else if (nr_bytes == 0)
333
    nr_bytes_written = 0;
334
  else if (fseek(disk->image, addr, SEEK_SET) < 0)
335
    nr_bytes_written = 0;
336
  else if (fwrite(source, nr_bytes, 1, disk->image) != 1)
337
    nr_bytes_written = 0;
338
  else
339
    nr_bytes_written = nr_bytes;
340
  DTRACE(disk, ("io-write - address 0x%lx, nr-bytes-written %d, requested %d\n",
341
                (unsigned long) addr, (int)nr_bytes_written, (int)nr_bytes));
342
  return nr_bytes_written;
343
}
344
 
345
 
346
/* instances of the hw_disk device */
347
 
348
static void
349
hw_disk_instance_delete(device_instance *instance)
350
{
351
  hw_disk_instance *data = device_instance_data(instance);
352
  DITRACE(disk, ("delete - instance=%ld\n",
353
                 (unsigned long)device_instance_to_external(instance)));
354
  zfree(data);
355
}
356
 
357
static int
358
hw_disk_instance_read(device_instance *instance,
359
                      void *buf,
360
                      unsigned_word len)
361
{
362
  hw_disk_instance *data = device_instance_data(instance);
363
  DITRACE(disk, ("read - instance=%ld len=%ld\n",
364
                 (unsigned long)device_instance_to_external(instance),
365
                 (long)len));
366
  if ((data->pos + len) < data->pos)
367
    return -1; /* overflow */
368
  if (fseek(data->disk->image, data->pos, SEEK_SET) < 0)
369
    return -1;
370
  if (fread(buf, len, 1, data->disk->image) != 1)
371
    return -1;
372
  data->pos = ftell(data->disk->image);
373
  return len;
374
}
375
 
376
static int
377
hw_disk_instance_write(device_instance *instance,
378
                       const void *buf,
379
                       unsigned_word len)
380
{
381
  hw_disk_instance *data = device_instance_data(instance);
382
  DITRACE(disk, ("write - instance=%ld len=%ld\n",
383
                 (unsigned long)device_instance_to_external(instance),
384
                 (long)len));
385
  if ((data->pos + len) < data->pos)
386
    return -1; /* overflow */
387
  if (data->disk->read_only)
388
    return -1;
389
  if (fseek(data->disk->image, data->pos, SEEK_SET) < 0)
390
    return -1;
391
  if (fwrite(buf, len, 1, data->disk->image) != 1)
392
    return -1;
393
  data->pos = ftell(data->disk->image);
394
  return len;
395
}
396
 
397
static int
398
hw_disk_instance_seek(device_instance *instance,
399
                      unsigned_word pos_hi,
400
                      unsigned_word pos_lo)
401
{
402
  hw_disk_instance *data = device_instance_data(instance);
403
  if (pos_hi != 0)
404
    device_error(device_instance_device(instance),
405
                 "seek - extended addressing unimplemented");
406
  DITRACE(disk, ("seek - instance=%ld pos_hi=%ld pos_lo=%ld\n",
407
                 (unsigned long)device_instance_to_external(instance),
408
                 (long)pos_hi, (long)pos_lo));
409
  data->pos = pos_lo;
410
  return 0;
411
}
412
 
413
static int
414
hw_disk_max_transfer(device_instance *instance,
415
                     int n_stack_args,
416
                     unsigned32 stack_args[/*n_stack_args*/],
417
                     int n_stack_returns,
418
                     unsigned32 stack_returns[/*n_stack_returns*/])
419
{
420
  device *me = device_instance_device(instance);
421
  if ((n_stack_args != 0)
422
      || (n_stack_returns != 1)) {
423
    device_error(me, "Incorrect number of arguments for max-transfer method\n");
424
    return -1;
425
  }
426
  else {
427
    unsigned_cell max_transfer;
428
    if (device_find_property(me, "max-transfer"))
429
      max_transfer = device_find_integer_property(me, "max-transfer");
430
    else
431
      max_transfer = 512;
432
    DITRACE(disk, ("max-transfer - instance=%ld max-transfer=%ld\n",
433
                   (unsigned long)device_instance_to_external(instance),
434
                   (long int)max_transfer));
435
    stack_returns[0] = max_transfer;
436
    return 0;
437
  }
438
}
439
 
440
static int
441
hw_disk_block_size(device_instance *instance,
442
                   int n_stack_args,
443
                   unsigned32 stack_args[/*n_stack_args*/],
444
                   int n_stack_returns,
445
                   unsigned32 stack_returns[/*n_stack_returns*/])
446
{
447
  device *me = device_instance_device(instance);
448
  if ((n_stack_args != 0)
449
      || (n_stack_returns != 1)) {
450
    device_error(me, "Incorrect number of arguments for block-size method\n");
451
    return -1;
452
  }
453
  else {
454
    unsigned_cell block_size;
455
    if (device_find_property(me, "block-size"))
456
      block_size = device_find_integer_property(me, "block-size");
457
    else
458
      block_size = 512;
459
    DITRACE(disk, ("block-size - instance=%ld block-size=%ld\n",
460
                   (unsigned long)device_instance_to_external(instance),
461
                   (long int)block_size));
462
    stack_returns[0] = block_size;
463
    return 0;
464
  }
465
}
466
 
467
static int
468
hw_disk_nr_blocks(device_instance *instance,
469
                  int n_stack_args,
470
                  unsigned32 stack_args[/*n_stack_args*/],
471
                  int n_stack_returns,
472
                  unsigned32 stack_returns[/*n_stack_returns*/])
473
{
474
  device *me = device_instance_device(instance);
475
  if ((n_stack_args != 0)
476
      || (n_stack_returns != 1)) {
477
    device_error(me, "Incorrect number of arguments for block-size method\n");
478
    return -1;
479
  }
480
  else {
481
    unsigned_word nr_blocks;
482
    if (device_find_property(me, "#blocks"))
483
      nr_blocks = device_find_integer_property(me, "#blocks");
484
    else
485
      nr_blocks = -1;
486
    DITRACE(disk, ("#blocks - instance=%ld #blocks=%ld\n",
487
                   (unsigned long)device_instance_to_external(instance),
488
                   (long int)nr_blocks));
489
    stack_returns[0] = nr_blocks;
490
    return 0;
491
  }
492
}
493
 
494
static device_instance_methods hw_disk_instance_methods[] = {
495
  { "max-transfer", hw_disk_max_transfer },
496
  { "block-size", hw_disk_block_size },
497
  { "#blocks", hw_disk_nr_blocks },
498
  { NULL, },
499
};
500
 
501
static const device_instance_callbacks hw_disk_instance_callbacks = {
502
  hw_disk_instance_delete,
503
  hw_disk_instance_read,
504
  hw_disk_instance_write,
505
  hw_disk_instance_seek,
506
  hw_disk_instance_methods,
507
};
508
 
509
static device_instance *
510
hw_disk_create_instance(device *me,
511
                        const char *path,
512
                        const char *args)
513
{
514
  device_instance *instance;
515
  hw_disk_device *disk = device_data(me);
516
  hw_disk_instance *data = ZALLOC(hw_disk_instance);
517
  data->disk = disk;
518
  data->pos = 0;
519
  instance = device_create_instance_from(me, NULL,
520
                                         data,
521
                                         path, args,
522
                                         &hw_disk_instance_callbacks);
523
  DITRACE(disk, ("create - path=%s(%s) instance=%ld\n",
524
                 path, args,
525
                 (unsigned long)device_instance_to_external(instance)));
526
  return pk_disklabel_create_instance(instance, args);
527
}
528
 
529
static device_callbacks const hw_disk_callbacks = {
530
  { hw_disk_init_address, NULL },
531
  { NULL, }, /* address */
532
  { hw_disk_io_read_buffer,
533
      hw_disk_io_write_buffer, },
534
  { NULL, }, /* DMA */
535
  { NULL, }, /* interrupt */
536
  { NULL, }, /* unit */
537
  hw_disk_create_instance,
538
  hw_disk_ioctl,
539
};
540
 
541
 
542
static void *
543
hw_disk_create(const char *name,
544
               const device_unit *unit_address,
545
               const char *args)
546
{
547
  /* create the descriptor */
548
  hw_disk_device *hw_disk = ZALLOC(hw_disk_device);
549
  return hw_disk;
550
}
551
 
552
 
553
const device_descriptor hw_disk_device_descriptor[] = {
554
  { "disk", hw_disk_create, &hw_disk_callbacks },
555
  { "cdrom", hw_disk_create, &hw_disk_callbacks },
556
  { "floppy", hw_disk_create, &hw_disk_callbacks },
557
  { NULL },
558
};
559
 
560
#endif /* _HW_DISK_C_ */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.