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

📄 hw_opic.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
  opic->nr_interprocessor_interrupts = 4;  opic->nr_timer_interrupts = 4;  /* create space for the interrupt source registers */  if (opic->interrupt_source != NULL) {    memset(opic->interrupt_source, 0, opic->sizeof_interrupt_source);  }  else {    opic->nr_interrupt_sources = (opic->nr_external_interrupts				  + opic->nr_interprocessor_interrupts				  + opic->nr_timer_interrupts);    if (opic->nr_interrupt_sources > max_nr_interrupt_sources)      device_error(me, "number of interrupt sources exceeded");    opic->sizeof_interrupt_source = (sizeof(opic_interrupt_source)				     * opic->nr_interrupt_sources);    opic->interrupt_source = zalloc(opic->sizeof_interrupt_source);    opic->external_interrupt_source = opic->interrupt_source;    opic->interprocessor_interrupt_source = (opic->external_interrupt_source					     + opic->nr_external_interrupts);    opic->timer_interrupt_source = (opic->interprocessor_interrupt_source				    + opic->nr_interprocessor_interrupts);  }  for (i = 0; i < opic->nr_interrupt_sources; i++) {    opic_interrupt_source *source = &opic->interrupt_source[i];    source->nr = i;    source->is_masked = isu_mask_bit;  }  DTRACE(opic, ("interrupt sources - external %d, timer %d, ipi %d, total %d\n",		opic->nr_external_interrupts,		opic->nr_timer_interrupts,		opic->nr_interprocessor_interrupts,		opic->nr_interrupt_sources));  /* timers or interprocessor interrupts */  if (opic->timer != NULL)    memset(opic->timer, 0, opic->sizeof_timer);  else {    opic->nr_timer_interrupts = 4;    opic->sizeof_timer = sizeof(opic_timer) * opic->nr_timer_interrupts;    opic->timer = zalloc(opic->sizeof_timer);  }  for (i = 0; i < opic->nr_timer_interrupts; i++) {    opic_timer *timer = &opic->timer[i];    timer->nr = i;    timer->me = me;    timer->opic = opic;    timer->inhibited = 1;    timer->interrupt_source = &opic->timer_interrupt_source[i];  }  if (device_find_property(me, "timer-frequency"))    opic->timer_frequency = device_find_integer_property(me, "timer-frequency");  else    opic->timer_frequency = 1;  /* create space for the interrupt destination registers */  if (opic->interrupt_destination != NULL) {    memset(opic->interrupt_destination, 0, opic->sizeof_interrupt_destination);  }  else {    opic->nr_interrupt_destinations = tree_find_integer_property(me, "/openprom/options/smp");    opic->sizeof_interrupt_destination = (sizeof(opic_interrupt_destination)					  * opic->nr_interrupt_destinations);    opic->interrupt_destination = zalloc(opic->sizeof_interrupt_destination);    if (opic->nr_interrupt_destinations > max_nr_interrupt_destinations)      device_error(me, "number of interrupt destinations exceeded");  }  for (i = 0; i < opic->nr_interrupt_destinations; i++) {    opic_interrupt_destination *dest = &opic->interrupt_destination[i];    dest->bit = (1 << i);    dest->nr = i;    dest->init_port = (device_interrupt_decode(me, "init0", output_port)		       + i);    dest->intr_port = (device_interrupt_decode(me, "intr0", output_port)		       + i);    dest->base_priority = max_nr_task_priorities - 1;  }  DTRACE(opic, ("interrupt destinations - total %d\n",		(int)opic->nr_interrupt_destinations));    /* verify and print out the ISU's */  for (isb = 0; isb < opic->nr_isu_blocks; isb++) {    unsigned correct_size;    if ((opic->isu_block[isb].address % opic_alignment) != 0)      device_error(me, "interrupt source unit %d address not aligned to %d byte boundary",		   isb, opic_alignment);    correct_size = opic->isu_block[isb].range * sizeof_isu_register_block;    if (opic->isu_block[isb].size != correct_size)      device_error(me, "interrupt source unit %d (reg %d) has an incorrect size, should be 0x%x",		   isb, opic->isu_block[isb].reg, correct_size);    DTRACE(opic, ("interrupt source unit block %ld - address %d:0x%lx, size 0x%lx, int-number %ld, range %ld\n",		  (long)isb,		  (int)opic->isu_block[isb].space,		  (unsigned long)opic->isu_block[isb].address,		  (unsigned long)opic->isu_block[isb].size,		  (long)opic->isu_block[isb].int_number,		  (long)opic->isu_block[isb].range));  }  /* verify and print out the IDU */  {    unsigned correct_size;    unsigned alternate_size;    if ((opic->idu.address % opic_alignment) != 0)      device_error(me, "interrupt delivery unit not aligned to %d byte boundary",		   opic_alignment);    correct_size = (idu_per_processor_register_base		    + (sizeof_idu_per_processor_register_block		       * opic->nr_interrupt_destinations));    alternate_size = (idu_per_processor_register_base		      + (sizeof_idu_per_processor_register_block			 * max_nr_interrupt_destinations));    if (opic->idu.size != correct_size	&& opic->idu.size != alternate_size)      device_error(me, "interrupt delivery unit has incorrect size, should be 0x%x or 0x%x",		   correct_size, alternate_size);    DTRACE(opic, ("interrupt delivery unit - address %d:0x%lx, size 0x%lx\n",		  (int)opic->idu.space,		  (unsigned long)opic->idu.address,		  (unsigned long)opic->idu.size));  }  /* initialize the init interrupts */  opic->init = 0;  /* vendor ident */  if (device_find_property(me, "vendor-identification") != NULL)    opic->vendor_identification = device_find_integer_property(me, "vendor-identification");  else    opic->vendor_identification = 0;  /* misc registers */  opic->spurious_vector = 0xff;}/* interrupt related actions */static voidassert_interrupt(device *me,		 hw_opic_device *opic,		 opic_interrupt_destination *dest){  ASSERT(dest >= opic->interrupt_destination);  ASSERT(dest < opic->interrupt_destination + opic->nr_interrupt_destinations);  DTRACE(opic, ("assert interrupt - intr port %d\n", dest->intr_port));  device_interrupt_event(me, dest->intr_port, 1, NULL, 0);}static voidnegate_interrupt(device *me,		 hw_opic_device *opic,		 opic_interrupt_destination *dest){  ASSERT(dest >= opic->interrupt_destination);  ASSERT(dest < opic->interrupt_destination + opic->nr_interrupt_destinations);  DTRACE(opic, ("negate interrupt - intr port %d\n", dest->intr_port));  device_interrupt_event(me, dest->intr_port, 0, NULL, 0);}static intcan_deliver(device *me,	    opic_interrupt_source *source,	    opic_interrupt_destination *dest){  return (source != NULL && dest != NULL	  && source->priority > dest->base_priority	  && (dest->current_in_service == NULL	      || source->priority > dest->current_in_service->priority));}static unsigneddeliver_pending(device *me,		hw_opic_device *opic,		opic_interrupt_destination *dest){  ASSERT(can_deliver(me, dest->current_pending, dest));  dest->current_in_service = dest->current_pending;  dest->current_in_service->in_service |= dest->bit;  if (!dest->current_pending->is_level_triggered) {    if (dest->current_pending->is_multicast)      dest->current_pending->pending &= ~dest->bit;    else      dest->current_pending->pending = 0;  }  dest->current_pending = NULL;  negate_interrupt(me, opic, dest);  return dest->current_in_service->vector;}typedef enum {  pending_interrupt,  in_service_interrupt,} interrupt_class;static opic_interrupt_source *find_interrupt_for_dest(device *me,			hw_opic_device *opic,			opic_interrupt_destination *dest,			interrupt_class class){  int i;  opic_interrupt_source *pending = NULL;  for (i = 0; i < opic->nr_interrupt_sources; i++) {    opic_interrupt_source *src = &opic->interrupt_source[i];    /* is this a potential hit? */    switch (class) {    case in_service_interrupt:      if ((src->in_service & dest->bit) == 0)	continue;      break;    case pending_interrupt:      if ((src->pending & dest->bit) == 0)	continue;      break;    }    /* see if it is the highest priority */    if (pending == NULL)      pending = src;    else if (src->priority > pending->priority)      pending = src;  }  return pending;}static opic_interrupt_destination *find_lowest_dest(device *me, 		 hw_opic_device *opic,		 opic_interrupt_source *src){  int i;  opic_interrupt_destination *lowest = NULL;  for (i = 0; i < opic->nr_interrupt_destinations; i++) {    opic_interrupt_destination *dest = &opic->interrupt_destination[i];    if (src->destination & dest->bit) {      if (dest->base_priority < src->priority) {	if (lowest == NULL)	  lowest = dest;	else if (lowest->base_priority > dest->base_priority)	  lowest = dest;	else if (lowest->current_in_service != NULL		 && dest->current_in_service == NULL)	  lowest = dest; /* not doing anything */	else if (lowest->current_in_service != NULL		 && dest->current_in_service != NULL		 && (lowest->current_in_service->priority		     > dest->current_in_service->priority))	  lowest = dest; /* less urgent */	/* FIXME - need to be more fair */	      }    }  }  return lowest;}static voidhandle_interrupt(device *me,		 hw_opic_device *opic,		 opic_interrupt_source *src,		 int asserted){  if (src->is_masked) {    DTRACE(opic, ("interrupt %d - ignore masked\n", src->nr));  }  else if (src->is_multicast) {    /* always try to deliver multicast interrupts - just easier */    int i;    ASSERT(!src->is_level_triggered);    ASSERT(src->is_positive_polarity);    ASSERT(asserted);    for (i = 0; i < opic->nr_interrupt_destinations; i++) {      opic_interrupt_destination *dest = &opic->interrupt_destination[i];      if (src->destination & dest->bit) {	if (src->pending & dest->bit) {	  DTRACE(opic, ("interrupt %d - multicast still pending to %d\n",			src->nr, dest->nr));	}	else if (can_deliver(me, src, dest)) {	  dest->current_pending = src;	  src->pending |= dest->bit;	  assert_interrupt(me, opic, dest);	  DTRACE(opic, ("interrupt %d - multicast to %d\n",			src->nr, dest->nr));	}	else {	  src->pending |= dest->bit;	  DTRACE(opic, ("interrupt %d - multicast pending to %d\n",			src->nr, dest->nr));	}      }    }  }  else if (src->is_level_triggered	   && src->is_positive_polarity	   && !asserted) {    if (src->pending)      DTRACE(opic, ("interrupt %d - ignore withdrawn (active high)\n",		    src->nr));    else      DTRACE(opic, ("interrupt %d - ignore low level (active high)\n",		    src->nr));    ASSERT(!src->is_multicast);    src->pending = 0;  }  else if (src->is_level_triggered	   && !src->is_positive_polarity	   && asserted) {    if (src->pending)      DTRACE(opic, ("interrupt %d - ignore withdrawn (active low)\n",		    src->nr));    else      DTRACE(opic, ("interrupt %d - ignore high level (active low)\n",		    src->nr));    ASSERT(!src->is_multicast);    src->pending = 0;  }  else if (!src->is_level_triggered	   && src->is_positive_polarity	   && !asserted) {    DTRACE(opic, ("interrupt %d - ignore falling edge (positive edge trigered)\n",		  src->nr));  }  else if (!src->is_level_triggered	   && !src->is_positive_polarity	   && asserted) {    DTRACE(opic, ("interrupt %d - ignore rising edge (negative edge trigered)\n",		  src->nr));  }  else if (src->in_service != 0) {    /* leave the interrupt where it is */    ASSERT(!src->is_multicast);    ASSERT(src->pending == 0 || src->pending == src->in_service);    src->pending = src->in_service;    DTRACE(opic, ("interrupt %ld - ignore already in service to 0x%lx\n",		  (long)src->nr, (long)src->in_service));  }  else if (src->pending != 0) {    DTRACE(opic, ("interrupt %ld - ignore still pending to 0x%lx\n",		  (long)src->nr, (long)src->pending));  }  else {    /* delivery is needed */    opic_interrupt_destination *dest = find_lowest_dest(me, opic, src);    if (can_deliver(me, src, dest)) {      dest->current_pending = src;      src->pending = dest->bit;      DTRACE(opic, ("interrupt %d - delivered to %d\n", src->nr, dest->nr));      assert_interrupt(me, opic, dest);    }    else {      src->pending = src->destination; /* any can take this */      DTRACE(opic, ("interrupt %ld - pending to 0x%lx\n",		    (long)src->nr, (long)src->pending));    }  }}static unsigneddo_interrupt_acknowledge_register_N_read(device *me,					 hw_opic_device *opic,					 int dest_nr){  opic_interrupt_destination *dest = &opic->interrupt_destination[dest_nr];  unsigned vector;  ASSERT(dest_nr >= 0 && dest_nr < opic->nr_interrupt_destinations);  ASSERT(dest_nr == dest->nr);  /* try the current pending */  if (can_deliver(me, dest->current_pending, dest)) {    ASSERT(dest->current_pending->pending & dest->bit);    vector = deliver_pending(me, opic, dest);    DTRACE(opic, ("interrupt ack %d - entering %d (pending) - vector %d (%d), priority %d\n",		  dest->nr,		  dest->current_in_service->nr,		  dest->current_in_service->vector, vector,		  dest->current_in_service->priority));  }  else {    /* try for something else */    dest->current_pending = find_interrupt_for_dest(me, opic, dest, pending_interrupt);    if (can_deliver(me, dest->current_pending, dest)) {      vector = deliver_pending(me, opic, dest);          DTRACE(opic, ("interrupt ack %d - entering %d (not pending) - vector %d (%d), priority %d\n",		    dest->nr,		    dest->current_in_service->nr,		    dest->current_in_service->vector, vector,		    dest->current_in_service->priority));    }    else {      dest->current_pending = NULL;      vector = opic->spurious_vector;      DTRACE(opic, ("interrupt ack %d - spurious interrupt %d\n",		    dest->nr, vector));    }  }  return vector;}static voiddo_end_of_interrupt_register_N_write(device *me,				     hw_opic_device *opic,				     int dest_nr,				     unsigned reg){  opic_interrupt_destination *dest = &opic->interrupt_destination[dest_nr];  ASSERT(dest_nr >= 0 && dest_nr < opic->nr_interrupt_destinations);  ASSERT(dest_nr == dest->nr);  /* check the value written is zero */  if (reg != 0) {    DTRACE(opic, ("eoi %d - ignoring nonzero value\n", dest->nr));  }  /* user doing wierd things? */  if (dest->current_in_service == NULL) {    DTRACE(opic, ("eoi %d - strange, no current interrupt\n", dest->nr));    return;  }  /* an internal stuff up? */  if (!(dest->current_in_service->in_service & dest->bit)) {    device_error(me, "eoi %d - current interrupt not in service", dest->nr);  }  /* find what was probably the previous in service interrupt */  dest->current_in_service->in_service &= ~dest->bit;  DTRACE(opic, ("eoi %d - ending %d - priority %d, vector %d\n",		dest->nr,		dest->current_in_service->nr,		dest->current_in_service->priority,		dest->current_in_service->vector));  dest->current_in_service = find_interrupt_for_dest(me, opic, dest, in_service_interrupt);  if (dest->current_in_service != NULL)    DTRACE(opic, ("eoi %d - resuming %d - priority %d, vector %d\n",		  dest->nr,		  dest->current_in_service->nr,		  dest->current_in_service->priority,		  dest->current_in_service->vector));  else    DTRACE(opic, ("eoi %d - resuming none\n", dest->nr));

⌨️ 快捷键说明

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