⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hw_ide.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  This file is part of the program psim.    Copyright (C) 1996, Andrew Cagney <cagney@highland.com.au>    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.     You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.     */#ifndef _HW_IDE_C_#define _HW_IDE_C_#include "device_table.h"/* DEVICE   ide - Integrated Disk Electronics   DESCRIPTION   This device models the primary/secondary <<ide>> controller   described in the [CHRPIO] document.   The controller has separate independant interrupt outputs for each   <<ide>> bus.   PROPERTIES   reg = ...  (required)   The <<reg>> property is described in the document [CHRPIO].   ready-delay = <integer>  (optional)   If present, this specifies the time that the <<ide>> device takes   to complete an I/O operation.   disk@?/ide-byte-count = <integer>  (optional)   disk@?/ide-sector-count = <integer>  (optional)   disk@?/ide-head-count = <integer>  (optional)   The <<ide>> device checks each child (disk device) node to see if   it has the above properties.  If present, these values will be used   to compute the <<LBA>> address in <<CHS>> addressing mode.   EXAMPLES   Enable tracing:   |  -t ide-device \   Attach the <<ide>> device to the <<pci>> bus at slot one.  Specify   legacy I/O addresses:   |  -o '/phb/ide@1/assigned-addresses \   |        ni0,0,10,1f0 8 \   |        ni0,0,14,3f8 8 \   |        ni0,0,18,170 8 \   |        ni0,0,1c,378 8 \   |        ni0,0,20,200 8' \   |  -o '/phb@0x80000000/ide@1/reg \   |        1 0 \   |        i0,0,10,0 8 \   |        i0,0,18,0 8 \   |        i0,0,14,6 1 \   |        i0,0,1c,6 1 \   |        i0,0,20,0 8' \   Note: the fouth and fifth reg entries specify that the register is   at an offset into the address specified by the base register   (<<assigned-addresses>>); Apart from restrictions placed by the   <<pci>> specification, no restrictions are placed on the number of   base registers specified by the <<assigned-addresses>> property.      Attach a <<disk>> to the primary and a <<cdrom>> to the secondary   <<ide>> controller.   |  -o '/phb@0x80000000/ide@1/disk@0/file "zero' \   |  -o '/phb@0x80000000/ide@1/cdrom@2/file "/dev/cdrom"' \   Connect the two interrupt outputs (a and b) to a <<glue>> device to   allow testing of the interrupt port. In a real simulation they   would be wired to the interrupt controller.   |  -o '/phb@0x80000000/glue@2/reg 2 0 ni0,0,0,0 8' \   |  -o '/phb@0x80000000/ide@1 > a 0 /phb@0x80000000/glue@2' \   |  -o '/phb@0x80000000/ide@1 > b 1 /phb@0x80000000/glue@2'       BUGS      While the DMA registers are present, DMA support has not yet been   implemented.   The number of supported commands is very limited.   The standards documents appear to be vague on how to specify the   <<unit-address>> of disk devices devices being attached to the   <<ide>> controller.  I've chosen to use integers with devices zero   and one going to the primary controller while two and three are   connected to the secondary controller.   REFERENCES   [CHRPIO] PowerPC(tm) Microprocessor Common Hardware Reference   Platform: I/O Device Reference.  http://chrp.apple.com/???.   [SCHMIDT] The SCSI Bus and IDE Interface - Protocols, Applications   and Programming.  Friedhelm Schmidt (translated by Michael   Schultz).  ISBN 0-201-42284-0.  Addison-Wesley Publishing Company.   */   typedef enum _io_direction {  is_read,  is_write,} io_direction;enum {  nr_ide_controllers = 2,  nr_ide_drives_per_controller = 2,  nr_fifo_entries = 8192,};enum {  /* command register block - read */  ide_data_reg,  ide_error_reg, /*ide_feature_reg*/  ide_sector_count_reg,  ide_sector_number_reg,  ide_cylinder_reg0,  ide_cylinder_reg1,  ide_drive_head_reg,  ide_status_reg, /*ide_command_reg*/  /* command register block - write */  ide_feature_reg, /*ide_error_reg*/  ide_command_reg, /*ide_status_reg*/  /* control register block - read */  ide_alternate_status_reg, /*ide_control_reg*/  ide_control_reg, /*ide_alternate_status_reg*/  /* dma register block */  ide_dma_command_reg,  ide_dma_unused_1_reg,  ide_dma_status_reg,  ide_dma_unused_3_reg,  ide_dma_prd_table_address_reg0,  ide_dma_prd_table_address_reg1,  ide_dma_prd_table_address_reg2,  ide_dma_prd_table_address_reg3,  nr_ide_registers,};typedef enum _ide_states {  idle_state,  busy_loaded_state,  busy_drained_state,  busy_dma_state,  busy_command_state,  loading_state,  draining_state,} ide_states;static const char *ide_state_name(ide_states state){  switch (state) {  case idle_state: return "idle";  case busy_loaded_state: return "busy_loaded_state";  case busy_drained_state: return "busy_drained_state";  case busy_dma_state: return "busy_dma_state";  case busy_command_state: return "busy_command_state";  case loading_state: return "loading_state";  case draining_state: return "draining_state";  default: return "illegal-state";  }}typedef struct _ide_geometry {  int head;  int sector;  int byte;} ide_geometry;typedef struct _ide_drive {  int nr;  device *device;  ide_geometry geometry;  ide_geometry default_geometry;} ide_drive;typedef struct _ide_controller {  int nr;  ide_states state;  unsigned8 reg[nr_ide_registers];  unsigned8 fifo[nr_fifo_entries];  int fifo_pos;  int fifo_size;  ide_drive *current_drive;  int current_byte;  int current_transfer;  ide_drive drive[nr_ide_drives_per_controller];  device *me;  event_entry_tag event_tag;  int is_interrupting;  signed64 ready_delay;} ide_controller;static voidset_interrupt(device *me,	      ide_controller *controller){  if ((controller->reg[ide_control_reg] & 0x2) == 0) {    DTRACE(ide, ("controller %d - interrupt set\n", controller->nr));    device_interrupt_event(me, controller->nr, 1, NULL, 0);    controller->is_interrupting = 1;  }}static voidclear_interrupt(device *me,		ide_controller *controller){  if (controller->is_interrupting) {    DTRACE(ide, ("controller %d - interrupt clear\n", controller->nr));    device_interrupt_event(me, controller->nr, 0, NULL, 0);    controller->is_interrupting = 0;  }}static voiddo_event(void *data){  ide_controller *controller = data;  device *me = controller->me;  controller->event_tag = 0;  switch (controller->state) {  case busy_loaded_state:  case busy_drained_state:    if (controller->current_transfer > 0) {      controller->state = (controller->state == busy_loaded_state			   ? loading_state : draining_state);    }    else {      controller->state = idle_state;    }    set_interrupt(me, controller);    break;  default:    device_error(me, "controller %d - unexpected event", controller->nr);    break;  }}static voidschedule_ready_event(device *me,		     ide_controller *controller){  if (controller->event_tag != 0)    device_error(me, "controller %d - attempting to schedule multiple events",		 controller->nr);  controller->event_tag =     device_event_queue_schedule(me, controller->ready_delay,				do_event, controller);}static voiddo_fifo_read(device *me,	     ide_controller *controller,	     void *dest,	     int nr_bytes){  if (controller->state != draining_state)    device_error(me, "controller %d - reading fifo when not ready (%s)",		 controller->nr,		 ide_state_name(controller->state));  if (controller->fifo_pos + nr_bytes > controller->fifo_size)    device_error(me, "controller %d - fifo underflow", controller->nr);  if (nr_bytes > 0) {    memcpy(dest, &controller->fifo[controller->fifo_pos], nr_bytes);    controller->fifo_pos += nr_bytes;  }  if (controller->fifo_pos == controller->fifo_size) {    controller->current_transfer -= 1;    if (controller->current_transfer > 0	&& controller->current_drive != NULL) {      DTRACE(ide, ("controller %d:%d - reading %d byte block at 0x%x\n",		   controller->nr,		   controller->current_drive->nr,		   controller->fifo_size,		   controller->current_byte));      if (device_io_read_buffer(controller->current_drive->device,				controller->fifo,				0, controller->current_byte,				controller->fifo_size,				NULL, 0)	  != controller->fifo_size)	device_error(me, "controller %d - disk %s io read error",		     controller->nr,		     device_path(controller->current_drive->device));    }    controller->state = busy_drained_state;    controller->fifo_pos = 0;    controller->current_byte += controller->fifo_size;    schedule_ready_event(me, controller);  }}static voiddo_fifo_write(device *me,	      ide_controller *controller,	      const void *source,	      int nr_bytes){  if (controller->state != loading_state)    device_error(me, "controller %d - writing fifo when not ready (%s)",		 controller->nr,		 ide_state_name(controller->state));  if (controller->fifo_pos + nr_bytes > controller->fifo_size)    device_error(me, "controller %d - fifo overflow", controller->nr);  if (nr_bytes > 0) {    memcpy(&controller->fifo[controller->fifo_pos], source, nr_bytes);    controller->fifo_pos += nr_bytes;  }  if (controller->fifo_pos == controller->fifo_size) {    if (controller->current_transfer > 0	&& controller->current_drive != NULL) {      DTRACE(ide, ("controller %d:%d - writing %d byte block at 0x%x\n",		   controller->nr,		   controller->current_drive->nr,		   controller->fifo_size,		   controller->current_byte));      if (device_io_write_buffer(controller->current_drive->device,				 controller->fifo,				 0, controller->current_byte,				 controller->fifo_size,				 NULL, 0)	  != controller->fifo_size)	device_error(me, "controller %d - disk %s io write error",		     controller->nr,		     device_path(controller->current_drive->device));    }    controller->current_transfer -= 1;    controller->fifo_pos = 0;    controller->current_byte += controller->fifo_size;    controller->state = busy_loaded_state;    schedule_ready_event(me, controller);  }}static voidsetup_fifo(device *me,	   ide_controller *controller,	   int is_simple,	   int is_with_disk,	   io_direction direction){  /* find the disk */  if (is_with_disk) {    int drive_nr = (controller->reg[ide_drive_head_reg] & 0x10) != 0;    controller->current_drive = &controller->drive[drive_nr];  }  else {    controller->current_drive = NULL;  }  /* number of transfers */  if (is_simple)    controller->current_transfer = 1;  else {    int sector_count = controller->reg[ide_sector_count_reg];    if (sector_count == 0)      controller->current_transfer = 256;    else      controller->current_transfer = sector_count;  }  /* the transfer size */  if (controller->current_drive == NULL)    controller->fifo_size = 512;  else    controller->fifo_size = controller->current_drive->geometry.byte;  /* empty the fifo */  controller->fifo_pos = 0;  /* the starting address */  if (controller->current_drive == NULL)    controller->current_byte = 0;  else if (controller->reg[ide_drive_head_reg] & 0x40) {    /* LBA addressing mode */    controller->current_byte = controller->fifo_size      * (((controller->reg[ide_drive_head_reg] & 0xf) << 24)	 | (controller->reg[ide_cylinder_reg1] << 16)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -