[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: PowerPC: new_exceptions status
Hello Nickolay,
the two exception handling schemes are definitively a problem for
portable drivers (and everything in libchip).
Attached you will find a patch that is not nice, but it works at least
for powerpc BSPs (or at least one BSP :-)) This patch is aganst
rtems-4.6.2, but should work with other versions aswell.
wkr,
Thomas.
Nickolay Kolchin schrieb:
> Hello,
>
> It looks like new_exceptions model in current RTEMS CVS tree is a stub
> and don't work in reality. The problem is in _CPU_ISR_install_vector
> definitions (/c/src/lib/libbsp/powerpc/new-exceptions/cpu.c)
>
> void _CPU_ISR_install_vector(
> uint32_t vector,
> proc_ptr new_handler,
> proc_ptr *old_handler
> )
> {
> BSP_panic("_CPU_ISR_install_vector called\n");
> }
>
> This mean that rtems_interrupt_catch function don't work and it is
> used in ATA driver (/c/src/libchip/ide/ata.c).
>
> Can somebody clarify what is current status of new_exceptions
> interface in PowerPC and what should be used instead of
> rtems_interrupt_catch?
>
> --
> Nickolay
--
--------------------------------------------
IMD Ingenieurbuero fuer Microcomputertechnik
Thomas Doerfler Herbststrasse 8
D-82178 Puchheim Germany
email: Thomas.Doerfler@imd-systems.de
PGP public key available at:
http://www.imd-systems.de/pgp_keys.html
--- rtems-4.6.2/c/src/libchip/ide/ata.c 2003-09-04 20:46:04.000000000 +0200
+++ rtems-4.6.2-bigimfs-ackhack/./c/src/libchip/ide/ata.c 2004-11-26 13:13:06.000000000 +0100
@@ -26,11 +26,31 @@
#include <libchip/ide_ctrl_cfg.h>
#include "ata_internal.h"
#include <libchip/ata.h>
+/* #define DEBUG */
+#include <stdio.h>
-#define DEBUG
+/*
+ * FIXME: make this better...
+ * find out, which exception model is used
+ * assume, that all i386 BSPs use new exception handling
+ * assume, that some PPC BSPs use new exception handling
+ * assume, that all other BSPs use old exception handling
+ */
+#if defined(_OLD_EXCEPTIONS) || (!defined(__i386__) && !defined(__PPC__))
-#ifdef DEBUG
-#include <stdio.h>
+#define ATA_USE_OLD_EXCEPTIONS
+#endif
+
+#if !defined(ATA_USE_OLD_EXCEPTIONS)
+#include <bsp/irq.h>
+#define ATA_IRQ_CHAIN_MAX_CNT 4 /* support up to 4 ATA devices */
+typedef struct {
+ rtems_irq_symbolic_name irq_symbolic_name;
+ Chain_Control irq_chain;
+} ata_irq_chain_t;
+
+ata_irq_chain_t ata_irq_chain[ATA_IRQ_CHAIN_MAX_CNT];
+int ata_irq_chain_cnt = 0;
#endif
#define SAFE
@@ -95,8 +115,10 @@
static rtems_id ata_task_id;
static rtems_id ata_queue_id;
+#if defined (ATA_USE_OLD_EXCEPTIONS)
/* Mapping of interrupt vectors to devices */
static Chain_Control ata_int_vec[ATA_MAX_RTEMS_INT_VEC_NUMBER + 1];
+#endif
static void
ata_process_request(rtems_device_minor_number ctrl_minor);
@@ -135,7 +157,7 @@
*/
rtems_device_minor_number ctrl_minor;
unsigned8 dev;
-
+
rel_minor = (rtems_filesystem_dev_minor_t(device)) /
ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE;
@@ -554,11 +576,12 @@
Chain_Append(&ata_ide_ctrls[ctrl_minor].reqs, &areq->link);
if (Chain_Has_only_one_node(&ata_ide_ctrls[ctrl_minor].reqs))
{
- unsigned16 val;
+
ata_queue_msg_t msg;
#ifdef DEBUG
- /*
+ unsigned16 val;
+ /*
* read IDE_REGISTER_ALTERNATE_STATUS instead IDE_REGISTER_STATUS
* to prevent clearing of pending interrupt
*/
@@ -584,6 +607,7 @@
* RETURNS:
* NONE
*/
+#if defined(ATA_USE_OLD_EXCEPTIONS)
rtems_isr
ata_interrupt_handler(rtems_vector_number vec)
{
@@ -607,8 +631,109 @@
the_node = the_node->next;
}
}
+#else
+
+void ata_interrupt_handler(int ata_irq_chain_index)
+{
+ Chain_Node *the_node =
+ ata_irq_chain[ata_irq_chain_index].irq_chain.last;
+ ata_queue_msg_t msg;
+ unsigned16 byte; /* emphasize that only 8 low bits is meaningful */
+
+
+ for ( ; !Chain_Is_tail(&ata_irq_chain[ata_irq_chain_index].irq_chain,
+ the_node) ; )
+ {
+ /* if (1) - is temporary hack - currently I don't know how to identify
+ * controller which asserted interrupt if few controllers share one
+ * interrupt line
+ */
+ if (1)
+ {
+ msg.ctrl_minor = ((ata_int_st_t *)the_node)->ctrl_minor;
+ ide_controller_read_register(msg.ctrl_minor, IDE_REGISTER_STATUS,
+ &byte);
+ ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, msg.ctrl_minor, 0);
+ }
+ the_node = the_node->next;
+ }
+}
+
+void ata_interrupt_handler_0(void)
+{
+ ata_interrupt_handler(0);
+}
-/* ata_pio_in_protocol --
+void ata_interrupt_handler_1(void)
+{
+ ata_interrupt_handler(1);
+}
+
+void ata_interrupt_handler_2(void)
+{
+ ata_interrupt_handler(2);
+}
+
+void ata_interrupt_handler_3(void)
+{
+ ata_interrupt_handler(3);
+}
+
+rtems_irq_hdl ata_int_hdl[ATA_IRQ_CHAIN_MAX_CNT] = {
+ ata_interrupt_handler_0,
+ ata_interrupt_handler_1,
+ ata_interrupt_handler_2,
+ ata_interrupt_handler_3
+};
+
+void ata_interrupt_on(const rtems_irq_connect_data *ptr)
+ {
+
+ /* enable ATA device interrupt */
+ ide_controller_write_register(0,
+ IDE_REGISTER_DEVICE_CONTROL_OFFSET,
+ 0x00
+ );
+ }
+
+
+void ata_interrupt_off(const rtems_irq_connect_data *ptr)
+ {
+
+ /* disable ATA device interrupt */
+ ide_controller_write_register(0,
+ IDE_REGISTER_DEVICE_CONTROL_OFFSET,
+ IDE_REGISTER_DEVICE_CONTROL_nIEN
+ );
+ }
+
+
+int ata_interrupt_isOn(const rtems_irq_connect_data *ptr)
+ {
+ unsigned16 byte; /* emphasize that only 8 low bits is meaningful */
+
+ /* return int. status od ATA device */
+ ide_controller_read_register(0,
+ IDE_REGISTER_DEVICE_CONTROL_OFFSET,
+ &byte
+ );
+
+ return !(byte & IDE_REGISTER_DEVICE_CONTROL_nIEN);
+ }
+
+
+static rtems_irq_connect_data ata_irq_data =
+ {
+
+ 0, /* filled out before use... */
+ (rtems_irq_hdl) ata_interrupt_handler_0,/* filled out before use... */
+ (rtems_irq_enable) ata_interrupt_on,
+ (rtems_irq_disable) ata_interrupt_off,
+ (rtems_irq_is_enabled) ata_interrupt_isOn
+ };
+#endif
+
+/* ata_pio_in_protocol --
* ATA PIO_IN protocol implementation, see specification
*
* PARAMETERS:
@@ -907,7 +1032,11 @@
char name[ATA_MAX_NAME_LENGTH];
dev_t device;
ata_int_st_t *int_st;
+#if defined(ATA_USE_OLD_EXCEPTIONS)
rtems_isr_entry old_isr;
+#else
+ int ata_irq_chain_use;
+#endif
if (ata_initialized)
return RTEMS_SUCCESSFUL;
@@ -976,9 +1105,15 @@
for (i = 0; i < (2 * IDE_CTRL_MAX_MINOR_NUMBER); i++)
ata_devs[i].device = ATA_UNDEFINED_VALUE;
+#if defined(ATA_USE_OLD_EXCEPTIONS)
/* prepare ATA driver for handling interrupt driven devices */
for (i = 0; i < ATA_MAX_RTEMS_INT_VEC_NUMBER; i++)
Chain_Initialize_empty(&ata_int_vec[i]);
+#else
+ for (i = 0; i < ATA_IRQ_CHAIN_MAX_CNT; i++) {
+ Chain_Initialize_empty(&(ata_irq_chain[i].irq_chain));
+ }
+#endif
/*
* during ATA driver initialization EXECUTE DEVICE DIAGNOSTIC and
@@ -1017,11 +1152,48 @@
}
int_st->ctrl_minor = ctrl_minor;
-
+#if defined(ATA_USE_OLD_EXCEPTIONS)
status = rtems_interrupt_catch(
ata_interrupt_handler,
IDE_Controller_Table[ctrl_minor].int_vec,
&old_isr);
+#else
+ /*
+ * FIXME: check existing entries. if they use the same
+ * IRQ name, then append int_st to respective chain
+ * otherwise, use new ata_irq_chain entry
+ */
+ ata_irq_chain_use = -1;
+ for (i = 0;
+ ((i < ata_irq_chain_cnt) &&
+ (ata_irq_chain_use < 0));i++) {
+ if (ata_irq_chain[i].irq_symbolic_name ==
+ IDE_Controller_Table[ctrl_minor].int_vec) {
+ ata_irq_chain_use = i;
+ }
+ }
+ if (ata_irq_chain_use < 0) {
+ /*
+ * no match found, try to use new channel entry
+ */
+ if (ata_irq_chain_cnt < ATA_IRQ_CHAIN_MAX_CNT) {
+ ata_irq_chain_use = ata_irq_chain_cnt++;
+
+ ata_irq_chain[ata_irq_chain_use].irq_symbolic_name =
+ IDE_Controller_Table[ctrl_minor].int_vec;
+ ata_irq_data.name =
+ IDE_Controller_Table[ctrl_minor].int_vec;
+ ata_irq_data.hdl = ata_int_hdl[ata_irq_chain_use];
+
+ status = ((0 == BSP_install_rtems_irq_handler(&ata_irq_data))
+ ? RTEMS_INVALID_NUMBER
+ : RTEMS_SUCCESSFUL);
+ }
+ else {
+ status = RTEMS_TOO_MANY;
+ }
+ }
+#endif
if (status != RTEMS_SUCCESSFUL)
{
free(int_st);
@@ -1031,9 +1203,15 @@
rtems_disk_io_done();
return status;
}
+#if defined(ATA_USE_OLD_EXCEPTIONS)
Chain_Append(
&ata_int_vec[IDE_Controller_Table[ctrl_minor].int_vec],
&int_st->link);
+#else
+ Chain_Append(
+ &(ata_irq_chain[ata_irq_chain_use].irq_chain),
+ &int_st->link);
+#endif
/* disable interrupts */
ide_controller_write_register(ctrl_minor,
@@ -1159,7 +1337,7 @@
ATA_DEV_INFO(ctrl_minor, dev).mode_active = ATA_MODES_PIO3;
}
else {
- ATA_DEV_INFO(ctrl_minor, dev).modes_avaible =
+ ATA_DEV_INFO(ctrl_minor, dev).modes_available =
((CF_LE_W(buffer[64]) & 0x1) ? ATA_MODES_PIO3 : 0) |
((CF_LE_W(buffer[64]) & 0x2) ? ATA_MODES_PIO4 : 0) |
((CF_LE_W(buffer[63]) & 0x1) ? ATA_MODES_DMA0 : 0) |
@@ -1167,7 +1345,7 @@
ATA_MODES_DMA0 | ATA_MODES_DMA1 : 0) |
((CF_LE_W(buffer[63]) & 0x4) ?
ATA_MODES_DMA0 | ATA_MODES_DMA1 | ATA_MODES_DMA2 : 0);
- if (ATA_DEV_INFO(ctrl_minor, dev).modes_avaible == 0)
+ if (ATA_DEV_INFO(ctrl_minor, dev).modes_available == 0)
continue;
/*
* choose most appropriate ATA device data I/O speed supported
@@ -1175,7 +1353,7 @@
*/
status = ide_controller_config_io_speed(
ctrl_minor,
- ATA_DEV_INFO(ctrl_minor, dev).modes_avaible);
+ ATA_DEV_INFO(ctrl_minor, dev).modes_available);
if (status != RTEMS_SUCCESSFUL)
continue;
}