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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [gdb-6.8/] [sim/] [ppc/] [hw_ide.c] - Blame information for rev 26

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 26 jlechner
/*  This file is part of the program psim.
2
 
3
    Copyright (C) 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_IDE_C_
23
#define _HW_IDE_C_
24
 
25
#include "device_table.h"
26
 
27
 
28
 
29
/* DEVICE
30
 
31
 
32
   ide - Integrated Disk Electronics
33
 
34
 
35
   DESCRIPTION
36
 
37
 
38
   This device models the primary/secondary <<ide>> controller
39
   described in the [CHRPIO] document.
40
 
41
   The controller has separate independant interrupt outputs for each
42
   <<ide>> bus.
43
 
44
 
45
   PROPERTIES
46
 
47
 
48
   reg = ...  (required)
49
 
50
   The <<reg>> property is described in the document [CHRPIO].
51
 
52
 
53
   ready-delay = <integer>  (optional)
54
 
55
   If present, this specifies the time that the <<ide>> device takes
56
   to complete an I/O operation.
57
 
58
 
59
   disk@?/ide-byte-count = <integer>  (optional)
60
 
61
   disk@?/ide-sector-count = <integer>  (optional)
62
 
63
   disk@?/ide-head-count = <integer>  (optional)
64
 
65
   The <<ide>> device checks each child (disk device) node to see if
66
   it has the above properties.  If present, these values will be used
67
   to compute the <<LBA>> address in <<CHS>> addressing mode.
68
 
69
 
70
   EXAMPLES
71
 
72
 
73
   Enable tracing:
74
 
75
   |  -t ide-device \
76
 
77
 
78
   Attach the <<ide>> device to the <<pci>> bus at slot one.  Specify
79
   legacy I/O addresses:
80
 
81
   |  -o '/phb/ide@1/assigned-addresses \
82
   |        ni0,0,10,1f0 8 \
83
   |        ni0,0,14,3f8 8 \
84
   |        ni0,0,18,170 8 \
85
   |        ni0,0,1c,378 8 \
86
   |        ni0,0,20,200 8' \
87
   |  -o '/phb@0x80000000/ide@1/reg \
88
   |        1 0 \
89
   |        i0,0,10,0 8 \
90
   |        i0,0,18,0 8 \
91
   |        i0,0,14,6 1 \
92
   |        i0,0,1c,6 1 \
93
   |        i0,0,20,0 8' \
94
 
95
   Note: the fouth and fifth reg entries specify that the register is
96
   at an offset into the address specified by the base register
97
   (<<assigned-addresses>>); Apart from restrictions placed by the
98
   <<pci>> specification, no restrictions are placed on the number of
99
   base registers specified by the <<assigned-addresses>> property.
100
 
101
   Attach a <<disk>> to the primary and a <<cdrom>> to the secondary
102
   <<ide>> controller.
103
 
104
   |  -o '/phb@0x80000000/ide@1/disk@0/file "zero' \
105
   |  -o '/phb@0x80000000/ide@1/cdrom@2/file "/dev/cdrom"' \
106
 
107
   Connect the two interrupt outputs (a and b) to a <<glue>> device to
108
   allow testing of the interrupt port. In a real simulation they
109
   would be wired to the interrupt controller.
110
 
111
   |  -o '/phb@0x80000000/glue@2/reg 2 0 ni0,0,0,0 8' \
112
   |  -o '/phb@0x80000000/ide@1 > a 0 /phb@0x80000000/glue@2' \
113
   |  -o '/phb@0x80000000/ide@1 > b 1 /phb@0x80000000/glue@2'
114
 
115
 
116
   BUGS
117
 
118
 
119
   While the DMA registers are present, DMA support has not yet been
120
   implemented.
121
 
122
   The number of supported commands is very limited.
123
 
124
   The standards documents appear to be vague on how to specify the
125
   <<unit-address>> of disk devices devices being attached to the
126
   <<ide>> controller.  I've chosen to use integers with devices zero
127
   and one going to the primary controller while two and three are
128
   connected to the secondary controller.
129
 
130
 
131
   REFERENCES
132
 
133
 
134
   [CHRPIO] PowerPC(tm) Microprocessor Common Hardware Reference
135
   Platform: I/O Device Reference.  http://chrp.apple.com/???.
136
 
137
   [SCHMIDT] The SCSI Bus and IDE Interface - Protocols, Applications
138
   and Programming.  Friedhelm Schmidt (translated by Michael
139
   Schultz).  ISBN 0-201-42284-0.  Addison-Wesley Publishing Company.
140
 
141
 
142
   */
143
 
144
 
145
 
146
typedef enum _io_direction {
147
  is_read,
148
  is_write,
149
} io_direction;
150
 
151
 
152
enum {
153
  nr_ide_controllers = 2,
154
  nr_ide_drives_per_controller = 2,
155
  nr_fifo_entries = 8192,
156
};
157
 
158
enum {
159
  /* command register block - read */
160
  ide_data_reg,
161
  ide_error_reg, /*ide_feature_reg*/
162
  ide_sector_count_reg,
163
  ide_sector_number_reg,
164
  ide_cylinder_reg0,
165
  ide_cylinder_reg1,
166
  ide_drive_head_reg,
167
  ide_status_reg, /*ide_command_reg*/
168
  /* command register block - write */
169
  ide_feature_reg, /*ide_error_reg*/
170
  ide_command_reg, /*ide_status_reg*/
171
  /* control register block - read */
172
  ide_alternate_status_reg, /*ide_control_reg*/
173
  ide_control_reg, /*ide_alternate_status_reg*/
174
  /* dma register block */
175
  ide_dma_command_reg,
176
  ide_dma_unused_1_reg,
177
  ide_dma_status_reg,
178
  ide_dma_unused_3_reg,
179
  ide_dma_prd_table_address_reg0,
180
  ide_dma_prd_table_address_reg1,
181
  ide_dma_prd_table_address_reg2,
182
  ide_dma_prd_table_address_reg3,
183
  nr_ide_registers,
184
};
185
 
186
 
187
typedef enum _ide_states {
188
  idle_state,
189
  busy_loaded_state,
190
  busy_drained_state,
191
  busy_dma_state,
192
  busy_command_state,
193
  loading_state,
194
  draining_state,
195
} ide_states;
196
 
197
static const char *
198
ide_state_name(ide_states state)
199
{
200
  switch (state) {
201
  case idle_state: return "idle";
202
  case busy_loaded_state: return "busy_loaded_state";
203
  case busy_drained_state: return "busy_drained_state";
204
  case busy_dma_state: return "busy_dma_state";
205
  case busy_command_state: return "busy_command_state";
206
  case loading_state: return "loading_state";
207
  case draining_state: return "draining_state";
208
  default: return "illegal-state";
209
  }
210
}
211
 
212
typedef struct _ide_geometry {
213
  int head;
214
  int sector;
215
  int byte;
216
} ide_geometry;
217
 
218
typedef struct _ide_drive {
219
  int nr;
220
  device *device;
221
  ide_geometry geometry;
222
  ide_geometry default_geometry;
223
} ide_drive;
224
 
225
typedef struct _ide_controller {
226
  int nr;
227
  ide_states state;
228
  unsigned8 reg[nr_ide_registers];
229
  unsigned8 fifo[nr_fifo_entries];
230
  int fifo_pos;
231
  int fifo_size;
232
  ide_drive *current_drive;
233
  int current_byte;
234
  int current_transfer;
235
  ide_drive drive[nr_ide_drives_per_controller];
236
  device *me;
237
  event_entry_tag event_tag;
238
  int is_interrupting;
239
  signed64 ready_delay;
240
} ide_controller;
241
 
242
 
243
 
244
static void
245
set_interrupt(device *me,
246
              ide_controller *controller)
247
{
248
  if ((controller->reg[ide_control_reg] & 0x2) == 0) {
249
    DTRACE(ide, ("controller %d - interrupt set\n", controller->nr));
250
    device_interrupt_event(me, controller->nr, 1, NULL, 0);
251
    controller->is_interrupting = 1;
252
  }
253
}
254
 
255
 
256
static void
257
clear_interrupt(device *me,
258
                ide_controller *controller)
259
{
260
  if (controller->is_interrupting) {
261
    DTRACE(ide, ("controller %d - interrupt clear\n", controller->nr));
262
    device_interrupt_event(me, controller->nr, 0, NULL, 0);
263
    controller->is_interrupting = 0;
264
  }
265
}
266
 
267
 
268
static void
269
do_event(void *data)
270
{
271
  ide_controller *controller = data;
272
  device *me = controller->me;
273
  controller->event_tag = 0;
274
  switch (controller->state) {
275
  case busy_loaded_state:
276
  case busy_drained_state:
277
    if (controller->current_transfer > 0) {
278
      controller->state = (controller->state == busy_loaded_state
279
                           ? loading_state : draining_state);
280
    }
281
    else {
282
      controller->state = idle_state;
283
    }
284
    set_interrupt(me, controller);
285
    break;
286
  default:
287
    device_error(me, "controller %d - unexpected event", controller->nr);
288
    break;
289
  }
290
}
291
 
292
 
293
static void
294
schedule_ready_event(device *me,
295
                     ide_controller *controller)
296
{
297
  if (controller->event_tag != 0)
298
    device_error(me, "controller %d - attempting to schedule multiple events",
299
                 controller->nr);
300
  controller->event_tag =
301
    device_event_queue_schedule(me, controller->ready_delay,
302
                                do_event, controller);
303
}
304
 
305
 
306
static void
307
do_fifo_read(device *me,
308
             ide_controller *controller,
309
             void *dest,
310
             int nr_bytes)
311
{
312
  if (controller->state != draining_state)
313
    device_error(me, "controller %d - reading fifo when not ready (%s)",
314
                 controller->nr,
315
                 ide_state_name(controller->state));
316
  if (controller->fifo_pos + nr_bytes > controller->fifo_size)
317
    device_error(me, "controller %d - fifo underflow", controller->nr);
318
  if (nr_bytes > 0) {
319
    memcpy(dest, &controller->fifo[controller->fifo_pos], nr_bytes);
320
    controller->fifo_pos += nr_bytes;
321
  }
322
  if (controller->fifo_pos == controller->fifo_size) {
323
    controller->current_transfer -= 1;
324
    if (controller->current_transfer > 0
325
        && controller->current_drive != NULL) {
326
      DTRACE(ide, ("controller %d:%d - reading %d byte block at 0x%x\n",
327
                   controller->nr,
328
                   controller->current_drive->nr,
329
                   controller->fifo_size,
330
                   controller->current_byte));
331
      if (device_io_read_buffer(controller->current_drive->device,
332
                                controller->fifo,
333
                                0, controller->current_byte,
334
                                controller->fifo_size,
335
                                NULL, 0)
336
          != controller->fifo_size)
337
        device_error(me, "controller %d - disk %s io read error",
338
                     controller->nr,
339
                     device_path(controller->current_drive->device));
340
    }
341
    controller->state = busy_drained_state;
342
    controller->fifo_pos = 0;
343
    controller->current_byte += controller->fifo_size;
344
    schedule_ready_event(me, controller);
345
  }
346
}
347
 
348
 
349
static void
350
do_fifo_write(device *me,
351
              ide_controller *controller,
352
              const void *source,
353
              int nr_bytes)
354
{
355
  if (controller->state != loading_state)
356
    device_error(me, "controller %d - writing fifo when not ready (%s)",
357
                 controller->nr,
358
                 ide_state_name(controller->state));
359
  if (controller->fifo_pos + nr_bytes > controller->fifo_size)
360
    device_error(me, "controller %d - fifo overflow", controller->nr);
361
  if (nr_bytes > 0) {
362
    memcpy(&controller->fifo[controller->fifo_pos], source, nr_bytes);
363
    controller->fifo_pos += nr_bytes;
364
  }
365
  if (controller->fifo_pos == controller->fifo_size) {
366
    if (controller->current_transfer > 0
367
        && controller->current_drive != NULL) {
368
      DTRACE(ide, ("controller %d:%d - writing %d byte block at 0x%x\n",
369
                   controller->nr,
370
                   controller->current_drive->nr,
371
                   controller->fifo_size,
372
                   controller->current_byte));
373
      if (device_io_write_buffer(controller->current_drive->device,
374
                                 controller->fifo,
375
                                 0, controller->current_byte,
376
                                 controller->fifo_size,
377
                                 NULL, 0)
378
          != controller->fifo_size)
379
        device_error(me, "controller %d - disk %s io write error",
380
                     controller->nr,
381
                     device_path(controller->current_drive->device));
382
    }
383
    controller->current_transfer -= 1;
384
    controller->fifo_pos = 0;
385
    controller->current_byte += controller->fifo_size;
386
    controller->state = busy_loaded_state;
387
    schedule_ready_event(me, controller);
388
  }
389
}
390
 
391
 
392
static void
393
setup_fifo(device *me,
394
           ide_controller *controller,
395
           int is_simple,
396
           int is_with_disk,
397
           io_direction direction)
398
{
399
  /* find the disk */
400
  if (is_with_disk) {
401
    int drive_nr = (controller->reg[ide_drive_head_reg] & 0x10) != 0;
402
    controller->current_drive = &controller->drive[drive_nr];
403
  }
404
  else {
405
    controller->current_drive = NULL;
406
  }
407
 
408
  /* number of transfers */
409
  if (is_simple)
410
    controller->current_transfer = 1;
411
  else {
412
    int sector_count = controller->reg[ide_sector_count_reg];
413
    if (sector_count == 0)
414
      controller->current_transfer = 256;
415
    else
416
      controller->current_transfer = sector_count;
417
  }
418
 
419
  /* the transfer size */
420
  if (controller->current_drive == NULL)
421
    controller->fifo_size = 512;
422
  else
423
    controller->fifo_size = controller->current_drive->geometry.byte;
424
 
425
  /* empty the fifo */
426
  controller->fifo_pos = 0;
427
 
428
  /* the starting address */
429
  if (controller->current_drive == NULL)
430
    controller->current_byte = 0;
431
  else if (controller->reg[ide_drive_head_reg] & 0x40) {
432
    /* LBA addressing mode */
433
    controller->current_byte = controller->fifo_size
434
      * (((controller->reg[ide_drive_head_reg] & 0xf) << 24)
435
         | (controller->reg[ide_cylinder_reg1] << 16)
436
         | (controller->reg[ide_cylinder_reg0] << 8)
437
         | (controller->reg[ide_sector_number_reg]));
438
  }
439
  else if (controller->current_drive->geometry.head != 0
440
           && controller->current_drive->geometry.sector != 0) {
441
    /* CHS addressing mode */
442
    int head_nr = controller->reg[ide_drive_head_reg] & 0xf;
443
    int cylinder_nr = ((controller->reg[ide_cylinder_reg1] << 8)
444
                    | controller->reg[ide_cylinder_reg0]);
445
    int sector_nr = controller->reg[ide_sector_number_reg];
446
    controller->current_byte = controller->fifo_size
447
      * ((cylinder_nr * controller->current_drive->geometry.head + head_nr)
448
         * controller->current_drive->geometry.sector + sector_nr - 1);
449
  }
450
  else
451
    device_error(me, "controller %d:%d - CHS addressing disabled",
452
                 controller->nr, controller->current_drive->nr);
453
  DTRACE(ide, ("controller %ld:%ld - transfer (%s) %ld blocks of %ld bytes from 0x%lx\n",
454
               (long)controller->nr,
455
               controller->current_drive == NULL ? -1L : (long)controller->current_drive->nr,
456
               direction == is_read ? "read" : "write",
457
               (long)controller->current_transfer,
458
               (long)controller->fifo_size,
459
               (unsigned long)controller->current_byte));
460
  switch (direction) {
461
  case is_read:
462
    /* force a primeing read */
463
    controller->current_transfer += 1;
464
    controller->state = draining_state;
465
    controller->fifo_pos = controller->fifo_size;
466
    do_fifo_read(me, controller, NULL, 0);
467
    break;
468
  case is_write:
469
    controller->state = loading_state;
470
    break;
471
  }
472
}
473
 
474
 
475
static void
476
do_command(device *me,
477
           ide_controller *controller,
478
           int command)
479
{
480
  if (controller->state != idle_state)
481
    device_error(me, "controller %d - command when not idle", controller->nr);
482
  switch (command) {
483
  case 0x20: case 0x21: /* read-sectors */
484
    setup_fifo(me, controller, 0/*is_simple*/, 1/*is_with_disk*/, is_read);
485
    break;
486
  case 0x30: case 0x31: /* write */
487
    setup_fifo(me, controller, 0/*is_simple*/, 1/*is_with_disk*/, is_write);
488
    break;
489
  }
490
}
491
 
492
static unsigned8
493
get_status(device *me,
494
           ide_controller *controller)
495
{
496
  switch (controller->state) {
497
  case loading_state:
498
  case draining_state:
499
    return 0x08; /* data req */
500
  case busy_loaded_state:
501
  case busy_drained_state:
502
    return 0x80; /* busy */
503
  case idle_state:
504
    return 0x40; /* drive ready */
505
  default:
506
    device_error(me, "internal error");
507
    return 0;
508
  }
509
}
510
 
511
 
512
/* The address presented to the IDE controler is decoded and then
513
   mapped onto a controller:reg pair */
514
 
515
enum {
516
  nr_address_blocks = 6,
517
};
518
 
519
typedef struct _address_block {
520
  int space;
521
  unsigned_word base_addr;
522
  unsigned_word bound_addr;
523
  int controller;
524
  int base_reg;
525
} address_block;
526
 
527
typedef struct _address_decoder {
528
  address_block block[nr_address_blocks];
529
} address_decoder;
530
 
531
static void
532
decode_address(device *me,
533
               address_decoder *decoder,
534
               int space,
535
               unsigned_word address,
536
               int *controller,
537
               int *reg,
538
               io_direction direction)
539
{
540
  int i;
541
  for (i = 0; i < nr_address_blocks; i++) {
542
    if (space == decoder->block[i].space
543
        && address >= decoder->block[i].base_addr
544
        && address <= decoder->block[i].bound_addr) {
545
      *controller = decoder->block[i].controller;
546
      *reg = (address
547
              - decoder->block[i].base_addr
548
              + decoder->block[i].base_reg);
549
      if (direction == is_write) {
550
        switch (*reg) {
551
        case ide_error_reg: *reg = ide_feature_reg; break;
552
        case ide_status_reg: *reg = ide_command_reg; break;
553
        case ide_alternate_status_reg: *reg = ide_control_reg; break;
554
        default: break;
555
        }
556
      }
557
      return;
558
    }
559
  }
560
  device_error(me, "address %d:0x%lx invalid",
561
               space, (unsigned long)address);
562
}
563
 
564
 
565
static void
566
build_address_decoder(device *me,
567
                      address_decoder *decoder)
568
{
569
  int reg;
570
  for (reg = 1; reg < 6; reg++) {
571
    reg_property_spec unit;
572
    int space;
573
    unsigned_word address;
574
    unsigned size;
575
    /* find and decode the reg property */
576
    if (!device_find_reg_array_property(me, "reg", reg, &unit))
577
      device_error(me, "missing or invalid reg entry %d", reg);
578
    device_address_to_attach_address(device_parent(me), &unit.address,
579
                                     &space, &address, me);
580
    device_size_to_attach_size(device_parent(me), &unit.size, &size, me);
581
    /* insert it into the address decoder */
582
    switch (reg) {
583
    case 1:
584
    case 2:
585
      /* command register block */
586
      if (size != 8)
587
        device_error(me, "reg entry %d must have a size of 8", reg);
588
      decoder->block[reg-1].space = space;
589
      decoder->block[reg-1].base_addr = address;
590
      decoder->block[reg-1].bound_addr = address + size - 1;
591
      decoder->block[reg-1].controller = (reg + 1) % nr_ide_controllers;
592
      decoder->block[reg-1].base_reg = ide_data_reg;
593
      DTRACE(ide, ("controller %d command register block at %d:0x%lx..0x%lx\n",
594
                   decoder->block[reg-1].controller,
595
                   decoder->block[reg-1].space,
596
                   (unsigned long)decoder->block[reg-1].base_addr,
597
                   (unsigned long)decoder->block[reg-1].bound_addr));
598
      break;
599
    case 3:
600
    case 4:
601
      /* control register block */
602
      if (size != 1)
603
        device_error(me, "reg entry %d must have a size of 1", reg);
604
      decoder->block[reg-1].space = space;
605
      decoder->block[reg-1].base_addr = address;
606
      decoder->block[reg-1].bound_addr = address + size - 1;
607
      decoder->block[reg-1].controller = (reg + 1) % nr_ide_controllers;
608
      decoder->block[reg-1].base_reg = ide_alternate_status_reg;
609
      DTRACE(ide, ("controller %d control register block at %d:0x%lx..0x%lx\n",
610
                   decoder->block[reg-1].controller,
611
                   decoder->block[reg-1].space,
612
                   (unsigned long)decoder->block[reg-1].base_addr,
613
                   (unsigned long)decoder->block[reg-1].bound_addr));
614
      break;
615
    case 5:
616
      /* dma register block */
617
      if (size != 8)
618
        device_error(me, "reg entry %d must have a size of 8", reg);
619
      decoder->block[reg-1].space = space;
620
      decoder->block[reg-1].base_addr = address;
621
      decoder->block[reg-1].bound_addr = address + 4 - 1;
622
      decoder->block[reg-1].base_reg = ide_dma_command_reg;
623
      decoder->block[reg-1].controller = 0;
624
      DTRACE(ide, ("controller %d dma register block at %d:0x%lx..0x%lx\n",
625
                   decoder->block[reg-1].controller,
626
                   decoder->block[reg-1].space,
627
                   (unsigned long)decoder->block[reg-1].base_addr,
628
                   (unsigned long)decoder->block[reg-1].bound_addr));
629
      decoder->block[reg].space = space;
630
      decoder->block[reg].base_addr = address + 4;
631
      decoder->block[reg].bound_addr = address + 8 - 1;
632
      decoder->block[reg].controller = 1;
633
      decoder->block[reg].base_reg = ide_dma_command_reg;
634
      DTRACE(ide, ("controller %d dma register block at %d:0x%lx..0x%lx\n",
635
                   decoder->block[reg].controller,
636
                   decoder->block[reg-1].space,
637
                   (unsigned long)decoder->block[reg].base_addr,
638
                   (unsigned long)decoder->block[reg].bound_addr));
639
      break;
640
    default:
641
      device_error(me, "internal error - bad switch");
642
      break;
643
    }
644
  }
645
}
646
 
647
 
648
 
649
typedef struct _hw_ide_device {
650
  ide_controller controller[nr_ide_controllers];
651
  address_decoder decoder;
652
} hw_ide_device;
653
 
654
 
655
static void
656
hw_ide_init_address(device *me)
657
{
658
  hw_ide_device *ide = device_data(me);
659
  int controller;
660
  int drive;
661
 
662
  /* zero some things */
663
  for (controller = 0; controller < nr_ide_controllers; controller++) {
664
    memset(&ide->controller[controller], 0, sizeof(ide_controller));
665
    for (drive = 0; drive < nr_ide_drives_per_controller; drive++) {
666
      ide->controller[controller].drive[drive].nr = drive;
667
    }
668
    ide->controller[controller].me = me;
669
    if (device_find_property(me, "ready-delay") != NULL)
670
      ide->controller[controller].ready_delay =
671
        device_find_integer_property(me, "ready-delay");
672
  }
673
 
674
  /* attach this device to its parent */
675
  generic_device_init_address(me);
676
 
677
  /* determine our own address map */
678
  build_address_decoder(me, &ide->decoder);
679
 
680
}
681
 
682
 
683
static void
684
hw_ide_attach_address(device *me,
685
                      attach_type type,
686
                      int space,
687
                      unsigned_word addr,
688
                      unsigned nr_bytes,
689
                      access_type access,
690
                      device *client) /*callback/default*/
691
{
692
  hw_ide_device *ide = (hw_ide_device*)device_data(me);
693
  int controller_nr = addr / nr_ide_drives_per_controller;
694
  int drive_nr = addr % nr_ide_drives_per_controller;
695
  ide_controller *controller;
696
  ide_drive *drive;
697
  if (controller_nr >= nr_ide_controllers)
698
    device_error(me, "no controller for disk %s",
699
                 device_path(client));
700
 
701
  controller = &ide->controller[controller_nr];
702
  drive = &controller->drive[drive_nr];
703
  drive->device = client;
704
  if (device_find_property(client, "ide-byte-count") != NULL)
705
    drive->geometry.byte = device_find_integer_property(client, "ide-byte-count");
706
  else
707
    drive->geometry.byte = 512;
708
  if (device_find_property(client, "ide-sector-count") != NULL)
709
    drive->geometry.sector = device_find_integer_property(client, "ide-sector-count");
710
  if (device_find_property(client, "ide-head-count") != NULL)
711
    drive->geometry.head = device_find_integer_property(client, "ide-head-count");
712
  drive->default_geometry = drive->geometry;
713
  DTRACE(ide, ("controller %d:%d %s byte-count %d, sector-count %d, head-count %d\n",
714
               controller_nr,
715
               drive->nr,
716
               device_path(client),
717
               drive->geometry.byte,
718
               drive->geometry.sector,
719
               drive->geometry.head));
720
}
721
 
722
 
723
static unsigned
724
hw_ide_io_read_buffer(device *me,
725
                      void *dest,
726
                      int space,
727
                      unsigned_word addr,
728
                      unsigned nr_bytes,
729
                      cpu *processor,
730
                      unsigned_word cia)
731
{
732
  hw_ide_device *ide = (hw_ide_device *)device_data(me);
733
  int control_nr;
734
  int reg;
735
  ide_controller *controller;
736
 
737
  /* find the interface */
738
  decode_address(me, &ide->decoder, space, addr, &control_nr, &reg, is_read);
739
  controller = & ide->controller[control_nr];
740
 
741
  /* process the transfer */
742
  memset(dest, 0, nr_bytes);
743
  switch (reg) {
744
  case ide_data_reg:
745
    do_fifo_read(me, controller, dest, nr_bytes);
746
    break;
747
  case ide_status_reg:
748
    *(unsigned8*)dest = get_status(me, controller);
749
    clear_interrupt(me, controller);
750
    break;
751
  case ide_alternate_status_reg:
752
    *(unsigned8*)dest = get_status(me, controller);
753
    break;
754
  case ide_error_reg:
755
  case ide_sector_count_reg:
756
  case ide_sector_number_reg:
757
  case ide_cylinder_reg0:
758
  case ide_cylinder_reg1:
759
  case ide_drive_head_reg:
760
  case ide_control_reg:
761
  case ide_dma_command_reg:
762
  case ide_dma_status_reg:
763
  case ide_dma_prd_table_address_reg0:
764
  case ide_dma_prd_table_address_reg1:
765
  case ide_dma_prd_table_address_reg2:
766
  case ide_dma_prd_table_address_reg3:
767
    *(unsigned8*)dest = controller->reg[reg];
768
    break;
769
  default:
770
    device_error(me, "bus-error at address 0x%lx", addr);
771
    break;
772
  }
773
  return nr_bytes;
774
}
775
 
776
 
777
static unsigned
778
hw_ide_io_write_buffer(device *me,
779
                       const void *source,
780
                       int space,
781
                       unsigned_word addr,
782
                       unsigned nr_bytes,
783
                       cpu *processor,
784
                       unsigned_word cia)
785
{
786
  hw_ide_device *ide = (hw_ide_device *)device_data(me);
787
  int control_nr;
788
  int reg;
789
  ide_controller *controller;
790
 
791
  /* find the interface */
792
  decode_address(me, &ide->decoder, space, addr, &control_nr, &reg, is_write);
793
  controller = &ide->controller[control_nr];
794
 
795
  /* process the access */
796
  switch (reg) {
797
  case ide_data_reg:
798
    do_fifo_write(me, controller, source, nr_bytes);
799
    break;
800
  case ide_command_reg:
801
    do_command(me, controller, *(unsigned8*)source);
802
    break;
803
  case ide_control_reg:
804
    controller->reg[reg] = *(unsigned8*)source;
805
    /* possibly cancel interrupts */
806
    if ((controller->reg[reg] & 0x02) == 0x02)
807
      clear_interrupt(me, controller);
808
    break;
809
  case ide_feature_reg:
810
  case ide_sector_count_reg:
811
  case ide_sector_number_reg:
812
  case ide_cylinder_reg0:
813
  case ide_cylinder_reg1:
814
  case ide_drive_head_reg:
815
  case ide_dma_command_reg:
816
  case ide_dma_status_reg:
817
  case ide_dma_prd_table_address_reg0:
818
  case ide_dma_prd_table_address_reg1:
819
  case ide_dma_prd_table_address_reg2:
820
  case ide_dma_prd_table_address_reg3:
821
    controller->reg[reg] = *(unsigned8*)source;
822
    break;
823
  default:
824
    device_error(me, "bus-error at 0x%lx", addr);
825
    break;
826
  }
827
  return nr_bytes;
828
}
829
 
830
 
831
static const device_interrupt_port_descriptor hw_ide_interrupt_ports[] = {
832
  { "a", 0, 0 },
833
  { "b", 1, 0 },
834
  { "c", 2, 0 },
835
  { "d", 3, 0 },
836
  { NULL }
837
};
838
 
839
 
840
 
841
static device_callbacks const hw_ide_callbacks = {
842
  { hw_ide_init_address, },
843
  { hw_ide_attach_address, }, /* attach */
844
  { hw_ide_io_read_buffer, hw_ide_io_write_buffer, },
845
  { NULL, }, /* DMA */
846
  { NULL, NULL, hw_ide_interrupt_ports }, /* interrupt */
847
  { generic_device_unit_decode,
848
    generic_device_unit_encode,
849
    generic_device_address_to_attach_address,
850
    generic_device_size_to_attach_size },
851
};
852
 
853
 
854
static void *
855
hw_ide_create(const char *name,
856
              const device_unit *unit_address,
857
              const char *args)
858
{
859
  hw_ide_device *ide = ZALLOC(hw_ide_device);
860
  return ide;
861
}
862
 
863
 
864
const device_descriptor hw_ide_device_descriptor[] = {
865
  { "ide", hw_ide_create, &hw_ide_callbacks },
866
  { NULL, },
867
};
868
 
869
#endif /* _HW_IDE_ */

powered by: WebSVN 2.1.0

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