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