/*-------------------------------------------------------------------------+ | Function: BSP_irq_enable_at_i8259s | Description: Unmask IRQ line in appropriate PIC chip. | Global Variables: i8259s_cache | Arguments: irqLine - number of IRQ line to mask. | Returns: Nothing. +--------------------------------------------------------------------------*/ int BSP_irq_enable_at_i8259s (const rtems_irq_number irqLine) { unsigned short mask; rtems_interrupt_level level; if ( ((int)irqLine < BSP_ISA_IRQ_LOWEST_OFFSET) || ((int)irqLine > BSP_ISA_IRQ_MAX_OFFSET ) ) return 1; rtems_interrupt_disable(level); mask = ~(1 << irqLine); i8259s_cache &= mask; if (irqLine < 8) { outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff); } else { outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8)); } rtems_interrupt_enable(level); return 0; } /* mask_irq */
int Timer_read() { register uint32_t clicks; register uint32_t total; /* outport_byte( TBCR, 0x00 ); stop the timer -- not needed on intel */ outport_byte ( TMRCON, 0x40 ); /* latch the count */ inport_byte ( TMR1, clicks ); /* read the count */ total = Ttimer_val + 250 - clicks; /* outport_byte( TBCR, 0x00 ); initial value */ /* outport_byte( IERA, 0x40 ); disable interrupt */ /* ??? Is "do not restore old vector" causing problems? */ if ( Timer_driver_Find_average_overhead == 1 ) return total; /* in one microsecond units */ else { if ( total < LEAST_VALID ) return 0; /* below timer resolution */ return (total - AVG_OVERHEAD); } }
static inline void BSP_irq_ack_at_i8259a(const int irqLine) { uint8_t slave_isr = 0; if (irqLine >= 8) { outport_byte(PIC_SLAVE_COMMAND_IO_PORT, PIC_EOI); slave_isr = BSP_i8259a_irq_in_service_reg(PIC_SLAVE_COMMAND_IO_PORT); } /* * Only issue the EOI to the master if there are no more interrupts in * service for the slave. i8259a data sheet page 18, The Special Fully Nested * Mode, b. */ if (slave_isr == 0) outport_byte(PIC_MASTER_COMMAND_IO_PORT, PIC_EOI); }
void TimerOn(const rtems_raw_irq_connect_data* used) { Ttimer_val = 0; /* clear timer ISR count */ outport_byte ( TMRCON , 0xb0 ); /* select tmr2, stay in mode 0 */ outport_byte ( TMR1 , 0xfa ); /* set to 250 usec interval */ outport_byte ( TMR1 , 0x00 ); outport_byte ( TMRCON , 0x64 ); /* change to mode 2 ( starts timer ) */ /* interrupts ARE enabled */ /* outport_byte( IERA, 0x41 ); enable interrupt */ /* * enable interrrupt at i8259 level */ BSP_irq_enable_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE); }
/*-------------------------------------------------------------------------+ | Function: rtcin | Description: Perform action on RTC and return its result. | Global Variables: None. | Arguments: what - what to write to RTC port (what to do). | Returns: result received from RTC port after action performed. +--------------------------------------------------------------------------*/ static inline uint8_t rtcin(uint8_t what) { uint8_t r; outport_byte(IO_RTC, what); inport_byte (IO_RTC+1, r); return r; } /* rtcin */
/* * Stop the device */ static void wd_stop (struct wd_softc *sc) { unsigned int tport; unsigned char temp; struct ifnet *ifp = &sc->arpcom.ac_if; ifp->if_flags &= ~IFF_RUNNING; /* * Stop the transmitter */ tport=wd_softc[0].port ; inport_byte(tport+0x04,temp); outport_byte(tport+0x04, temp & 0x7f); outport_byte(tport + CMDR, MSK_STP + MSK_RD2); }
rtems_device_driver Clock_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *pargp ) { unsigned timer_counter_init_value; unsigned char clock_lsb, clock_msb; Clock_driver_ticks = 0; Clock_isrs = Clock_initial_isr_value = rtems_configuration_get_microseconds_per_tick() / 1000; /* ticks per clock_isr */ /* * configure the counter timer ( should be based on microsecs/tick ) * NB. The divisor(Clock_isrs) resolves the is the same number that appears in confdefs.h * when setting the microseconds_per_tick value. */ ClockOff ( &clockIrqData ); timer_counter_init_value = rtems_configuration_get_microseconds_per_tick() / Clock_isrs; clock_lsb = (unsigned char)timer_counter_init_value; clock_msb = timer_counter_init_value >> 8; outport_byte ( TMRCON , 0x34 ); outport_byte ( TMR0 , clock_lsb ); /* load LSB first */ outport_byte ( TMR0 , clock_msb ); /* then MSB */ if (!BSP_install_rtems_irq_handler (&clockIrqData)) { printk("Unable to initialize system clock\n"); rtems_fatal_error_occurred(1); } /* * make major/minor avail to others such as shared memory driver */ rtems_clock_major = major; rtems_clock_minor = minor; return RTEMS_SUCCESSFUL; }
/*-------------------------------------------------------------------------+ | Function: init_rtc | Description: Initialize real-time clock (RTC). | Global Variables: None. | Arguments: None. | Returns: Nothing. +--------------------------------------------------------------------------*/ void init_rtc(void) { uint8_t s; /* initialize brain-dead battery powered clock */ outport_byte(IO_RTC, RTC_STATUSA); outport_byte(IO_RTC+1, 0x26); outport_byte(IO_RTC, RTC_STATUSB); outport_byte(IO_RTC+1, 2); outport_byte(IO_RTC, RTC_DIAG); inport_byte (IO_RTC+1, s); if (s) printk("RTC BIOS diagnostic error %b\n", s); /* FIXME: This was last line's original version. How was it supposed to work? printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS); */ } /* init_rtc */
uint8_t rtd316_com_get_register(uint32_t addr, uint8_t reg) { register uint8_t val = 0; outport_byte( addr, reg ); /* It appears the no delay is needed between the accesses. */ inport_byte( addr, val ); return val; }
void BSP_i8259s_init(void) { /* * init master 8259 interrupt controller */ outport_byte(PIC_MASTER_COMMAND_IO_PORT, 0x11); /* Start init sequence */ outport_byte(PIC_MASTER_IMR_IO_PORT, 0x00);/* Vector base = 0 */ outport_byte(PIC_MASTER_IMR_IO_PORT, 0x04);/* edge tiggered, Cascade (slave) on IRQ2 */ outport_byte(PIC_MASTER_IMR_IO_PORT, 0x01);/* Select 8086 mode */ outport_byte(PIC_MASTER_IMR_IO_PORT, 0xFB); /* Mask all except cascade */ /* * init slave interrupt controller */ outport_byte(PIC_SLAVE_COMMAND_IO_PORT, 0x11); /* Start init sequence */ outport_byte(PIC_SLAVE_IMR_IO_PORT, 0x08);/* Vector base = 8 */ outport_byte(PIC_SLAVE_IMR_IO_PORT, 0x02);/* edge triggered, Cascade (slave) on IRQ2 */ outport_byte(PIC_SLAVE_IMR_IO_PORT, 0x01); /* Select 8086 mode */ outport_byte(PIC_SLAVE_IMR_IO_PORT, 0xFF); /* Mask all */ }
/** * The head should be down or moves to this state. "wait" until * the HEAD_UP signal is false. don't literally wait, just * see if the head is down. If it is, begin retracting and set * RETRACT state. */ void control_punch(int * hole_to_punch) { uint32_t input; inport_byte(0x7071, input); if ((input & 1) == 0){ // is head down? outport_byte(OUT_PUNCH_IRQ, 0b10); // begin retract set_status(STATE_RETRACT); // status "head is moving up" *hole_to_punch += 1; // loop to the next hole newdest = 1; } }
void DEFUN_VOID(_Board_Initialize) { /* * FORCE documentation incorrectly states that the bus request * level is initialized to 3. It is actually initialized by * FORCEbug to 0. */ outport_byte( 0x00, 0x3f ); /* resets VMEbus request level */ _Console_Initialize(); }
static void sendpacket (struct ifnet *ifp, struct mbuf *m) { struct wd_softc *dp = ifp->if_softc; struct mbuf *n; unsigned int len, tport; uint8_t *shp, txReady; tport = dp->port; /* * Waiting for Transmitter ready */ inport_byte(tport+CMDR, txReady); while(txReady & MSK_TXP) inport_byte(tport+CMDR, txReady); len = 0; shp = dp->base + (SHAPAGE * OUTPAGE); n = m; for (;;){ len += m->m_len; memcpy(shp, (char *)m->m_data, m->m_len); shp += m->m_len ; if ((m = m->m_next) == NULL) break; } m_freem(n); if (len < ET_MINLEN) len = ET_MINLEN; outport_byte(tport+TBCR0, len); outport_byte(tport+TBCR1, (len >> 8) ); outport_byte(tport+TPSR, OUTPAGE); outport_byte(tport+CMDR, MSK_TXP + MSK_RD2); }
uint32_t mc146818a_get_register( uint32_t ulCtrlPort, uint8_t ucRegNum ) { uint8_t val; uint8_t tmp; outport_byte( ulCtrlPort, ucRegNum ); inport_byte( 0x84, tmp ); /* Hack a delay to give chip time to settle */ inport_byte( ulCtrlPort+1, val ); inport_byte( 0x84, tmp ); /* Hack a delay to give chip time to settle */ return val; }
/** * perform the actual punching. if the number of the hole is out of range, * we've just docked. so set the status to DONE. * * otherwise, set signal to punch (don't disable interrupts!) and hold * for 2ms */ void punch(int hole_to_punch, int holes_total_count) { if (hole_to_punch >= holes_total_count) { // docked, set status to DONE set_status(STATE_DONE); return; } // set the punch signal and hold for 2ms outport_byte(OUT_PUNCH_IRQ, 0b11); rtems_task_wake_after(get_ticks_for_period(2)); // set status PUNCHING (aka the head should be down) set_status(STATE_PUNCHING); }
/* * WD interrupt handler */ static void wd8003Enet_interrupt_handler (void *unused) { unsigned int tport; unsigned char status, status2; tport = wd_softc[0].port ; /* * Read status */ inport_byte(tport+ISR, status); outport_byte(tport+IMR, 0x00); /* * Ring overwrite */ if (status & MSK_OVW){ outport_byte(tport+CMDR, MSK_STP + MSK_RD2); /* stop 8390 */ Wait_X_ms(2); outport_byte(tport+RBCR0, 0); /* clear byte count */ outport_byte(tport+RBCR1, 0); inport_byte(tport+ISR, status2); status |= (status2 & (MSK_PTX+MSK_TXE)) ; /* TX status */ outport_byte(tport+TCR, MSK_LOOP); /* loopback mode */ outport_byte(tport+CMDR, MSK_STA + MSK_RD2); /* start */ overrun = 1 ; if ((status & (MSK_PTX+MSK_TXE)) == 0) resend = 1; } /* * Frame received? */ if (status & (MSK_PRX+MSK_RXE)) { outport_byte(tport+ISR, status & (MSK_PRX+MSK_RXE)); wd_softc[0].rxInterrupts++; rtems_event_send (wd_softc[0].rxDaemonTid, INTERRUPT_EVENT); } }
/* * High level IRQ handler called from shared_raw_irq_code_entry */ int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum) { register unsigned int irq; #if BSP_ISA_IRQ_NUMBER > 0 register unsigned isaIntr; /* boolean */ register unsigned oldMask = 0; /* old isa pic masks */ register unsigned newMask; /* new isa pic masks */ #endif if (excNum == ASM_DEC_VECTOR) { bsp_irq_dispatch_list(rtems_hdl_tbl, BSP_DECREMENTER, default_rtems_entry.hdl); return 0; } #if BSP_PCI_IRQ_NUMBER > 0 if ( OpenPIC ) { irq = openpic_irq(0); if (irq == OPENPIC_VEC_SPURIOUS) { ++BSP_spuriousIntr; return 0; } /* some BSPs might want to use a different numbering... */ irq = irq - OPENPIC_VEC_SOURCE + BSP_PCI_IRQ_LOWEST_OFFSET; } else { #if BSP_ISA_IRQ_NUMBER > 0 #ifdef BSP_PCI_ISA_BRIDGE_IRQ irq = BSP_PCI_ISA_BRIDGE_IRQ; #else #error "Configuration Error -- BSP with ISA + PCI IRQs MUST define BSP_PCI_ISA_BRIDGE_IRQ" #endif #else BSP_panic("MUST have an OpenPIC if BSP has PCI IRQs but no ISA IRQs"); /* BSP_panic() never returns but the 'return' statement silences * a compiler warning about 'irq' possibly being used w/o initialization. */ return -1; #endif } #endif #if BSP_ISA_IRQ_NUMBER > 0 #ifdef BSP_PCI_ISA_BRIDGE_IRQ #if 0 == BSP_PCI_IRQ_NUMBER #error "Configuration Error -- BSP w/o PCI IRQs MUST NOT define BSP_PCI_ISA_BRIDGE_IRQ" #endif isaIntr = (irq == BSP_PCI_ISA_BRIDGE_IRQ); #else isaIntr = 1; #endif if (isaIntr) { /* * Acknowledge and read 8259 vector */ irq = (unsigned int) (*(unsigned char *) RAVEN_INTR_ACK_REG); /* * store current PIC mask */ oldMask = i8259s_cache; newMask = oldMask | irq_mask_or_tbl [irq]; i8259s_cache = newMask; outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff); outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8)); BSP_irq_ack_at_i8259s (irq); #if BSP_PCI_IRQ_NUMBER > 0 if ( OpenPIC ) openpic_eoi(0); #endif } #endif /* dispatch handlers */ bsp_irq_dispatch_list(rtems_hdl_tbl, irq, default_rtems_entry.hdl); #if BSP_ISA_IRQ_NUMBER > 0 if (isaIntr) { i8259s_cache = oldMask; outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff); outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8)); } else #endif { #if BSP_PCI_IRQ_NUMBER > 0 #ifdef BSP_PCI_VME_DRIVER_DOES_EOI /* leave it to the VME bridge driver to do EOI, so * it can re-enable the openpic while handling * VME interrupts (-> VME priorities in software) */ if (_BSP_vme_bridge_irq != irq && OpenPIC)
void ClockOff(const rtems_irq_connect_data* unused) { outport_byte ( TMRCFG , 0x80 ); /* disable the counter timer */ }
/*-------------------------------------------------------------------------+ | Function: _IBMPC_scankey | Description: This function can be called during a poll for input, or by | an ISR. Basically any time you want to process a keypress. | Global Variables: key_map, shift_map. | Arguments: outChar - character read in case of a valid reading, | otherwise unchanged. | Returns: TRUE in case a valid character has been read, | FALSE otherwise. +--------------------------------------------------------------------------*/ static bool _IBMPC_scankey(char *outChar) { unsigned char inChar; static int alt_pressed = 0; static int ctrl_pressed = 0; static int shift_pressed = 0; static int caps_pressed = 0; static int extended = 0; *outChar = '\0'; /* default value if we return false */ /* Read keyboard controller, toggle enable */ inport_byte(KBD_CTL, inChar); outport_byte(KBD_CTL, inChar & ~0x80); outport_byte(KBD_CTL, inChar | 0x80); outport_byte(KBD_CTL, inChar & ~0x80); /* See if it has data */ inport_byte(KBD_STATUS, inChar); if ((inChar & 0x01) == 0) return false; /* Read the data. Handle nonsense with shift, control, etc. */ inport_byte(KBD_DATA, inChar); if (extended) extended--; switch (inChar) { case 0xe0: extended = 2; return false; break; case 0x38: alt_pressed = 1; return false; break; case 0xb8: alt_pressed = 0; return false; break; case 0x1d: ctrl_pressed = 1; return false; break; case 0x9d: ctrl_pressed = 0; return false; break; case 0x2a: if (extended) return false; case 0x36: shift_pressed = 1; return false; break; case 0xaa: if (extended) return false; case 0xb6: shift_pressed = 0; return false; break; case 0x3a: caps_pressed = 1; return false; break; case 0xba: caps_pressed = 0; return false; break; case 0x53: if (ctrl_pressed && alt_pressed) bsp_reset(); /* ctrl+alt+del -> reboot */ break; /* * Ignore unrecognized keys--usually arrow and such */ default: if ((inChar & 0x80) || (inChar > 0x39)) /* High-bit on means key is being released, not pressed */ return false; break; } /* switch */ /* Strip high bit, look up in our map */ inChar &= 0x7f; if (ctrl_pressed) { *outChar = key_map[inChar]; *outChar &= 037; } else { *outChar = shift_pressed ? shift_map[inChar] : key_map[inChar]; if (caps_pressed) { if (*outChar >= 'A' && *outChar <= 'Z') *outChar += 'a' - 'A'; else if (*outChar >= 'a' && *outChar <= 'z') *outChar -= 'a' - 'A'; } } return true; } /* _IBMPC_scankey */
rtems_task Task2(rtems_task_argument ignored) { rtems_status_code status; rtems_id period_id; rtems_interval ticks; status = rtems_rate_monotonic_create( rtems_build_name( 'P', 'E', 'R', '2' ), &period_id ); ticks = get_ticks_for_period(50); // the punching will start with the first hole int hole_to_punch = 0; // we are about to punch holes_total_count holes int holes_total_count = 4; int error = 0; int done = 0; while(1) { status = rtems_rate_monotonic_period( period_id, ticks ); if(status == RTEMS_TIMEOUT) { break; // this is the end. the system missed a deadline, which is fatal. } int state = read_punchpress_state(); if (state < STATE_INITIAL) break; switch (state) { case STATE_READY: plan_movement(hole_to_punch, holes_total_count); break; case STATE_PUNCH_READY: punch(hole_to_punch, holes_total_count); break; case STATE_PUNCHING: control_punch(&hole_to_punch); break; case STATE_RETRACT: control_retract(); break; case STATE_NAVIGATING: break; case STATE_DONE: done = 1; break; default: error = 1; break; } if ((error + done) > 0){ break; } } if (error > 0) { printf("ERROR! SOMETHING WENT WRONG (UNEXPECTED STATE OR DEADLINE MISSED) IN TASK CONTROLLING PUNCHING!\n"); exit(1); } outport_byte(OUT_PUNCH_IRQ, 0); rtems_rate_monotonic_delete(period_id); rtems_semaphore_delete(state_semaphore_id); rtems_interrupt_handler_remove(5, isr, NULL); /** * The only way to shutdown the app is to invoke exit() before deleting the "last" task. * Since it is not very nice and it is not used in example apps, just delete the task. **/ rtems_task_delete(RTEMS_SELF); }
void ClockOn(const rtems_irq_connect_data* unused) { outport_byte (TIMER_CONFIG, 0x00 ); /* enable the counter timer */ }
static void wd_rxDaemon (void *arg) { unsigned int tport; struct ether_header *eh; struct wd_softc *dp = (struct wd_softc *)&wd_softc[0]; struct ifnet *ifp = &dp->arpcom.ac_if; struct mbuf *m; unsigned int i2; unsigned int len; volatile unsigned char start, next, current; unsigned char *shp, *temp; unsigned short *real_short_ptr; rtems_event_set events; tport = wd_softc[0].port ; for (;;){ rtems_bsdnet_event_receive (INTERRUPT_EVENT, RTEMS_WAIT|RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &events); for (;;){ inport_byte(tport+BNRY, start); outport_byte(tport+CMDR, MSK_PG1 + MSK_RD2); inport_byte(tport+CURR, current); outport_byte(tport+CMDR, MSK_PG0 + MSK_RD2); start += 1; if (start >= OUTPAGE){ start = 0; } if (current == start) break; /* real_short_ptr avoids cast on lvalue which gcc no longer allows */ shp = dp->base + 1 + (SHAPAGE * start); next = *shp++; real_short_ptr = (unsigned short *)shp; len = *(real_short_ptr)++ - 4; if (next >= OUTPAGE){ next = 0; } MGETHDR (m, M_WAIT, MT_DATA); MCLGET (m, M_WAIT); m->m_pkthdr.rcvif = ifp; temp = (unsigned char *) m->m_data; m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header); if ((i2 = (OUTPAGE - start) * SHAPAGE - 4) < len){ memcpy(temp, shp, i2); len -= i2; temp += i2; shp = dp->base; } memcpy(temp, shp, len); eh = mtod (m, struct ether_header *); m->m_data += sizeof(struct ether_header); ether_input (ifp, eh, m); outport_byte(tport+BNRY, next-1); } /* * Ring overwrite */ if (overrun){ outport_byte(tport+ISR, MSK_OVW); /* reset IR */ outport_byte(tport+TCR, 0); /* out of loopback */ if (resend == 1) outport_byte(tport+CMDR, MSK_TXP + MSK_RD2); /* resend */ resend = 0; overrun = 0; } outport_byte(tport+IMR, 0x15); /* re-enable IT rx */ } }
void bsp_reset(void) { /* shutdown and reboot */ outport_byte(0x64, 0xFE); /* use keyboard controler to do the job... */ }
rtems_device_driver Clock_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *pargp ) { unsigned timer_counter_init_value; unsigned char clock_lsb, clock_msb; #ifdef BSP_DEBUG printk("Initializing clock driver in Clock_initialize().\n"); #endif #ifdef LOAD_RTC_AT_START /* Initialize clock from on-board real time clock. This breaks the */ /* test code which assumes which assumes the application will do it. */ { rtems_time_of_day now; #ifdef BSP_DEBUG printk("Loading clock from on-board real-time clock.\n"); #endif init_rtc(); if (rtc_read(&now) >= 0) rtems_clock_set(&now); } #endif Clock_driver_ticks = 0; Clock_isrs = Clock_initial_isr_value = rtems_configuration_get_microseconds_per_tick() / 1000; /* ticks per clock_isr */ /* * configure the counter timer ( should be based on microsecs/tick ) * NB. The divisor(Clock_isrs) resolves the is the same number that appears in confdefs.h * when setting the microseconds_per_tick value. */ ClockOff ( &clockIrqData ); timer_counter_init_value = rtems_configuration_get_microseconds_per_tick() / Clock_isrs; clock_lsb = (unsigned char)timer_counter_init_value; clock_msb = timer_counter_init_value >> 8; outport_byte (TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN); outport_byte (TIMER_CNTR0, clock_lsb ); /* load LSB first */ outport_byte (TIMER_CNTR0, clock_msb ); /* then MSB */ if (!BSP_install_rtems_irq_handler (&clockIrqData)) { printk("Unable to initialize system clock\n"); rtems_fatal_error_occurred(1); } /* * make major/minor avail to others such as shared memory driver */ rtems_clock_major = major; rtems_clock_minor = minor; return RTEMS_SUCCESSFUL; }
static void outb( unsigned short io_addr, unsigned char out_data ) { outport_byte( io_addr, out_data ); }
/*=========================================================================*\ | Function: | \*-------------------------------------------------------------------------*/ void pc386_ide_initialize ( /*-------------------------------------------------------------------------*\ | Purpose: | | initialize IDE access | +---------------------------------------------------------------------------+ | Input Parameters: | \*-------------------------------------------------------------------------*/ int minor /* controller minor number */ ) /*-------------------------------------------------------------------------*\ | Return Value: | | <none> | \*=========================================================================*/ { uint32_t port = IDE_Controller_Table[minor].port1; uint8_t dev = 0; if (pc386_ide_show) printk("IDE%d: port base: %04x\n", minor, port); outport_byte(port+IDE_REGISTER_DEVICE_HEAD, (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS) | 0xE0); wait(10000); outport_byte(port+IDE_REGISTER_DEVICE_CONTROL, IDE_REGISTER_DEVICE_CONTROL_SRST | IDE_REGISTER_DEVICE_CONTROL_nIEN); wait(10000); outport_byte(port+IDE_REGISTER_DEVICE_CONTROL, IDE_REGISTER_DEVICE_CONTROL_nIEN); wait(10000); for (dev = 0; dev < 2; dev++) { uint16_t capabilities = 0; uint32_t byte; uint8_t status; uint8_t error; uint8_t cyllsb; uint8_t cylmsb; const char* label = dev ? " slave" : "master"; int max_multiple_sectors = 0; int cur_multiple_sectors = 0; uint32_t cylinders = 0; uint32_t heads = 0; uint32_t sectors = 0; uint32_t lba_sectors = 0; char model_number[41]; char* p = &model_number[0]; bool data_ready; memset(model_number, 0, sizeof(model_number)); outport_byte(port+IDE_REGISTER_DEVICE_HEAD, (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS) | 0xE0); /* outport_byte(port+IDE_REGISTER_SECTOR_NUMBER, (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS) | IDE_REGISTER_LBA3_L); */ outport_byte(port+IDE_REGISTER_COMMAND, 0x00); if (!pc386_ide_status_busy (port, PC386_IDE_PROBE_TIMEOUT, &status, pc386_ide_prestart_sleep)) continue; inport_byte(port+IDE_REGISTER_STATUS, status); inport_byte(port+IDE_REGISTER_ERROR, error); inport_byte(port+IDE_REGISTER_CYLINDER_LOW, cyllsb); inport_byte(port+IDE_REGISTER_CYLINDER_HIGH, cylmsb); if (pc386_ide_show) { printk("IDE%d:%s: status=%02x\n", minor, label, status); printk("IDE%d:%s: error=%02x\n", minor, label, error); printk("IDE%d:%s: cylinder-low=%02x\n", minor, label, cyllsb); printk("IDE%d:%s: cylinder-high=%02x\n", minor, label, cylmsb); } outport_byte(port+IDE_REGISTER_COMMAND, 0xec); if (!pc386_ide_status_busy (port, PC386_IDE_PRESTART_TIMEOUT, &status, pc386_ide_prestart_sleep)) { if (pc386_ide_show) printk("IDE%d:%s: device busy: %02x\n", minor, label, status); continue; } data_ready = pc386_ide_status_data_ready (port, 250, &status, pc386_ide_prestart_sleep); if (status & IDE_REGISTER_STATUS_ERR) { inport_byte(port+IDE_REGISTER_ERROR, error); if (error != 4) { if (pc386_ide_show) printk("IDE%d:%s: error=%04x\n", minor, label, error); continue; } /* * The device is an ATAPI device. */ outport_byte(port+IDE_REGISTER_COMMAND, 0xa1); data_ready = pc386_ide_status_data_ready (port, 250, &status, pc386_ide_prestart_sleep); } if (!data_ready) continue; byte = 0; while (byte < 512) { uint16_t word; if (pc386_ide_show && ((byte % 16) == 0)) printk("\n %04x : ", byte); inport_word(port+IDE_REGISTER_DATA, word); if (pc386_ide_show) printk ("%04x ", word); if (byte == 2) cylinders = word; if (byte == 6) heads = word; if (byte == 12) sectors = word; if (byte >= 54 && byte < (54 + 40)) { *p = word >> 8; p++; *p = word; p++; } if (byte == (47 * 2)) max_multiple_sectors = word & 0xff; if (byte == (49 * 2)) capabilities = word; if (byte == (59 * 2)) { if (word & (1 << 8)) cur_multiple_sectors = word & 0xff; } if (byte == (60 * 2)) lba_sectors = word; if (byte == (61 * 2)) lba_sectors |= word << 16; byte += 2; } if (pc386_ide_show) printk("\nbytes read = %d\n", byte); if (p != &model_number[0]) { uint32_t size; uint32_t left; uint32_t right; char units; if (capabilities & (1 << 9)) size = lba_sectors; else size = cylinders * heads * sectors; size /= 2; if (size > (1024 * 1024)) { size = (size * 10) / (1000 * 1000); units = 'G'; } else if (size > 1024) { size = (size * 10) / 1000; units = 'M'; } else { size = size * 10; units = 'K'; } left = size / 10; right = size % 10; p--; while (*p == ' ') { *p = '\0'; p--; } printk("IDE%d:%s:%s, %u.%u%c (%u/%u/%u), max blk size:%d\n", minor, label, model_number, left, right, units, heads, cylinders, sectors, max_multiple_sectors * 512); } #if IDE_CLEAR_MULTI_SECTOR_COUNT if (max_multiple_sectors) { outport_byte(port+IDE_REGISTER_SECTOR_COUNT, 0); outport_byte(port+IDE_REGISTER_COMMAND, 0xc6); if (!pc386_ide_status_busy (port, PC386_IDE_PRESTART_TIMEOUT, &status, pc386_ide_prestart_sleep)) { if (pc386_ide_show) printk("IDE%d:%s: device busy: %02x\n", minor, label, status); continue; } inport_byte(port+IDE_REGISTER_STATUS, status); if (status & IDE_REGISTER_STATUS_ERR) { inport_byte(port+IDE_REGISTER_ERROR, error); if (error & IDE_REGISTER_ERROR_ABRT) printk("IDE%d:%s: disable multiple failed\n", minor, label); else printk("IDE%d:%s: unknown error on disable multiple: %02x\n", minor, label, error); } } #endif outport_byte(port+IDE_REGISTER_DEVICE_CONTROL, IDE_REGISTER_DEVICE_CONTROL_nIEN); wait(10000); }
/* * Initialize the ethernet hardware */ static void wd8003Enet_initialize_hardware (struct wd_softc *sc) { int i1, ultra; char cc1, cc2; unsigned char temp; rtems_status_code st; unsigned int tport; unsigned char *hwaddr; tport = sc->port; /* address from board ROM */ inport_byte(tport+0x04, temp); outport_byte(tport+0x04, temp & 0x7f); hwaddr = sc->arpcom.ac_enaddr; for (i1=cc2=0; i1<8; i1++) { inport_byte(tport + ADDROM + i1, cc1); cc2 += cc1; if (i1 < 6) hwaddr[i1] = cc1; } inport_byte(tport+0x04, temp); outport_byte(tport+0x04, temp | 0x80); /* alternate registers */ outport_byte(tport+W83CREG, MSK_RESET); /* reset board, set buffer */ outport_byte(tport+W83CREG, 0); outport_byte(tport+W83CREG, MSK_ENASH + (int)((sc->bpar>>13)&0x3f)); outport_byte(tport+CMDR, MSK_PG0 + MSK_RD2); cc1 = MSK_BMS + MSK_FT10; /* configure 8 or 16 bits */ inport_byte(tport+0x07, temp) ; ultra = ((temp & 0xf0) == 0x20 || (temp & 0xf0) == 0x40); if (ultra) cc1 = MSK_WTS + MSK_BMS + MSK_FT10; outport_byte(tport+DCR, cc1); outport_byte(tport+RBCR0, 0); outport_byte(tport+RBCR1, 0); outport_byte(tport+RCR, MSK_MON); /* disable the rxer */ outport_byte(tport+TCR, 0); /* normal operation */ outport_byte(tport+PSTOP, OUTPAGE); /* init PSTOP */ outport_byte(tport+PSTART, 0); /* init PSTART */ outport_byte(tport+BNRY, -1); /* init BNRY */ outport_byte(tport+ISR, -1); /* clear IR's */ outport_byte(tport+IMR, 0x15); /* enable interrupt */ outport_byte(tport+CMDR, MSK_PG1 + MSK_RD2); for (i1=0; i1<6; i1++) /* initial physical addr */ outport_byte(tport+PAR+i1, hwaddr[i1]); for (i1=0; i1<MARsize; i1++) /* clear multicast */ outport_byte(tport+MAR+i1, 0); outport_byte(tport+CURR, 0); /* init current packet */ outport_byte(tport+CMDR, MSK_PG0 + MSK_RD2); outport_byte(tport+CMDR, MSK_STA + MSK_RD2); /* put 8390 on line */ outport_byte(tport+RCR, MSK_AB); /* MSK_AB accept broadcast */ if (ultra) { inport_byte(tport+0x0c, temp); outport_byte(tport+0x0c, temp | 0x80); outport_byte(tport+0x05, 0x80); outport_byte(tport+0x06, 0x01); } /* * Set up interrupts */ sc->irqInfo.hdl = wd8003Enet_interrupt_handler; sc->irqInfo.on = nopOn; sc->irqInfo.off = nopOn; sc->irqInfo.isOn = wdIsOn; st = BSP_install_rtems_irq_handler (&sc->irqInfo); if (!st) rtems_panic ("Can't attach WD interrupt handler for irq %d\n", sc->irqInfo.name); }
void rtd316_com_set_register(uint32_t addr,uint8_t reg, uint8_t val) { outport_byte( addr, reg ); /* It appears the no delay is needed between the accesses. */ outport_byte( addr, val ); }
void com_set_register(uint32_t addr,uint8_t i, uint8_t val) { outport_byte( (addr+i),val ); }