📄 pcc850.c
字号:
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS inc, 1996
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
Last change: DZ 22 Feb 2000 5:21 pm
*/
#if (defined(ERTFS_SA))
#include "pcdisk.h"
#else
/* load RTIP configuration settings */
#include "xnconf.h"
#include "drvconf.h"
#include "rtip.h"
#endif
#if (INCLUDE_PCMCIA)
#include "pcmcia.h"
#if (defined(ERTFS_SA))
void hook_pcmcia_interrupt(int irq);
void pcmcia_irq_isr(void);
int map_slot_to_controller[2] = {-1,-1};
#endif
/*
* Configure PCMCIA Option Register 0 -- Configure as Read/Write
*
* ATA Card Memory Access Time: 300ns
* Assume: System Clock Frequency of 48MHz
* Settings Estimated According to Table 17-2, Section 17.4.1 U/M
*
* Bank Size = 64 megabytes (PCMCIA_BASE+0x0..0xf)
* Strobe Hold Time = 15 clocks
* Strobe Setup Time = 15 clocks
* Strobe Length = 30 clocks
* Port Size = 16 bit
* Region Select = Common Memory Space
* Slot Identifier = Slot B
* Write Protect = Off
* PCMCIA Valid Bit = Valid
*/
/* 860 otion register definitions
+ These constants are to be combined as is required using bitwise OR. */
/* EBS define PCMCIA bank addresses beginning at 0x100000. I'm not so sure this is
right for us. i am going to try to use a really high address. */
#define PCMCIA_BASE 0x10000000 // Base address for PCMCIA common memory accesses.
#define PCM8_BANKSIZE 0xB8000000 // 64 Megabyte banks
#define PCM8_STRBHOLD 0x000F0000 // 15 clocks
#define PCM8_STRBSETUP 0x0000F000 // 15 clocks
#define PCM8_STRBLENGTH 0x00000F00 // 30 clocks
#define PCM8_STROBE (PCM8_STRBHOLD|PCM8_STRBSETUP|PCM8_STRBLENGTH)
#define PCM8_PPS16 0x00000040 // 16 Bit window
#define PCM8_PPS8 0x00000000 // 8 Bit window
#define PCM8_MTYPE_COMMON 0
#define PCM8_MTYPE_ATTRIBUTE 0x10
#define PCM8_MTYPE_IO 0x18
#define PCM8_SLOTB 0x00000004 // Window mapped to slot B
#define PCM8_SLOTA 0x00000000 // Window mapped to slot A
#define PCM8_WP 0x00000002 // Write protected
#define PCM8_PV 0x00000001 // Base and options are valid
dword pcmcia_bank_address[7] =
{
PCMCIA_BASE,
0x20000000,
0x30000000,
0x40000000,
0x50000000,
0x60000000,
0x70000000
};
/* encoded bank size values */
dword pcmcia_bank_size[7] =
{
PCM8_BANKSIZE,
PCM8_BANKSIZE,
PCM8_BANKSIZE,
PCM8_BANKSIZE,
PCM8_BANKSIZE,
PCM8_BANKSIZE,
PCM8_BANKSIZE
};
#if (FADS860 || ADS860)
#if (FADS860 )
#define PCCEN (0x00800000) /* Enable PCMCIA on FADS860 */
#define PCMCIA_0V (0x00410000) /* 0V Setting -- Clear PCCVCC[0,1] */
#define PCMCIA_5V (0x00400000) /* 5 Volt VCC Setting -- Clear PCCVCC[0] */
#define PCMCIA_3V (0x00010000) /* 3 Volt VCC Setting -- Clear PCCVCC[1] */
/* Setup VPP Voltage Settings */
#define PCMCIA_0VPP (0x00300000) /* 0V Setting -- Clear PCCVPP[0,1] */
#define PCMCIA_5VPP (0x00200000) /* 5V Setting -- Clear PCCVPP[0] */
#define PCMCIA_12VPP (0x00100000) /* 12 Volt Setting -- Clear PCCVPP[1] */
#define PCMCIA_HIZPP (0x00300000) /* High Impedence Setting */
#elif (ADS860)
#define PCCEN (0x00800000) /* Enable PCMCIA on MPC821ADS */
#define PCCVCCON (0x00400000) /* Apply 5 Volt Vcc to PCMCIA Socket */
/* Setup VPP Voltage Settings */
#define PCMCIA_0VPP (0x00300000) /* 0V Setting -- Clear PCCVPP[0,1] */
#define PCMCIA_5VPP (0x00200000) /* 5V Setting -- Clear PCCVPP[0] */
#define PCMCIA_12VPP (0x00100000) /* 12 Volt Setting -- Clear PCCVPP[1] */
#define PCMCIA_HIZPP (0x00300000) /* High Impedence Setting */
#endif
/* Define bit combinations for interrupt sense and clear */
#define PCMCIA_ALL_AMGMT (PSCR_CAVS1_C|PSCR_CAVS2_C|PSCR_CAWP_C|PSCR_CACD2_C| \
PSCR_CACD1_C|PSCR_CABVD2_C|PSCR_CABVD1_C)
#define PCMCIA_ALL_AIRQ (PSCR_CARDY_L|PSCR_CARDY_H|PSCR_CARDY_R|PSCR_CARDY_F)
#define PCMCIA_ALL_BMGMT (PSCR_CBVS1_C|PSCR_CBVS2_C|PSCR_CBWP_C|PSCR_CBCD2_C| \
PSCR_CBCD1_C|PSCR_CBBVD2_C|PSCR_CBBVD1_C)
#define PCMCIA_ALL_BIRQ (PSCR_CBRDY_L|PSCR_CBRDY_H|PSCR_CBRDY_R|PSCR_CBRDY_F)
dword *at_bcsr1(void)
{
struct bcsr {
dword bcsr0;
dword bcsr1;
dword bcsr2;
dword bcsr3;
} *csr;
csr = (struct bcsr *) (IMMR->memc_br1 & 0xffff8000);
return(&csr->bcsr1);
}
#endif
/* Sets VCC voltage via board specific power control registers */
/* NOTE: Must Turn OFF VPP power supply. Not used in this ATA Flash devices.
This is done in pcmctrl_init. Provide pcm860_socket_vpppower function for
devices which need VPP */
void pcm860_socket_vccpower(int socket, int voltage /* 0,3 or 5 */)
{
#if (FADS860)
/* Ignore socket arg, we only have one control */
dword *bcsr1 = at_bcsr1();
*bcsr1 |= PCMCIA_0V; /* 0V default Voltage Level */
if (voltage == 0)
*bcsr1 &= ~PCMCIA_0V; /* 0 Volt Setting */
if (voltage == 3)
*bcsr1 &= ~PCMCIA_3V; /* 3 Volt Setting */
if (voltage == 5)
*bcsr1 &= ~PCMCIA_5V; /* 5 Volt Setting */
#elif (ADS860)
/* Ignore socket arg, we only have one control */
dword *bcsr1 = at_bcsr1();
*bcsr1 |= PCCVCCON; /* 0V default Voltage Level */
if (voltage == 3)
*bcsr1 &= ~PCCVCCON; /* 5 Volt Setting (no 3v on ADDS, use 5V) */
if (voltage == 5)
*bcsr1 &= ~PCCVCCON; /* 5 Volt Setting */
#elif(MPC860)
struct bcsr {
byte bcsr1; /* Board Control and Status Register */
byte bcsr2;
} *csr;
csr = (struct bcsr *) ((IMMR->memc_br4 & 0xffff8000) | 0x00100000);
if (voltage == 0)
csr->bcsr2 = 0x30|0x0e; /* VPP same as VCC VCC = HIZ E is all leds off */
elseif (voltage == 3)
csr->bcsr2 = 0xb0; /* 10110000 VPP same as VCC VCC = 3 */
elseif (voltage == 5)
csr->bcsr2 = 0x60|0x04; /* 01100000 VPP same as VCC VCC = 5 4 is led 0 & 2 on */
#else
#error - Implement power for unknown board
#endif
/* Delay 10 msecs for Power supply settling */
if (voltage > 0)
ks_sleep((word)(1+(10 + ks_msec_p_tick())/ks_msec_p_tick()));
}
/* Sets VPP voltage via board specific power control registers */
void pcm860_socket_vpppower(int socket, int voltage /* 0,5,12 or HiZ (not 0,3,5) */)
{
#if (FADS860 || ADS860)
/* Ignore socket arg, we only have one control */
dword *bcsr1 = at_bcsr1();
*bcsr1 |= PCMCIA_HIZPP; /* High Impedence default Voltage Level */
if (voltage == 0)
*bcsr1 &= ~PCMCIA_0VPP; /* 0 Volt Setting */
if (voltage == 5)
*bcsr1 &= ~PCMCIA_5VPP; /* 5 Volt Setting */
if (voltage == 12)
*bcsr1 &= ~PCMCIA_12VPP; /* 12 Volt Setting */
#elif(MPC860)
struct bcsr {
byte bcsr1; /* Board Control and Status Register */
byte bcsr2;
} *csr;
csr = (struct bcsr *) ((IMMR->memc_br4 & 0xffff8000) | 0x00100000);
if (voltage == 0)
csr->bcsr2 = 0x30|0x0e; /* VPP same as VCC VCC = HIZ E is all leds off */
elseif (voltage == 3)
csr->bcsr2 = 0xb0; /* 10110000 VPP same as VCC VCC = 3 */
elseif (voltage == 5)
csr->bcsr2 = 0x60|0x04; /* 01100000 VPP same as VCC VCC = 5 4 is led 0 & 2 on */
#else
#error - Implement power for unknown board
#endif
/* Delay 10 msecs for Power supply settling */
if (voltage > 0)
ks_sleep((word)(1+(10 + ks_msec_p_tick())/ks_msec_p_tick()));
}
/* Returns an index into pcmcia_bank_address & pcmcia_bank_size arrays which
are defined near the top of this file. */
int pcm860_socket_to_bank(int socket, int mem_type)
{
int bank;
if ( mem_type == PCM8_MTYPE_COMMON)
bank = 0;
else if ( mem_type == PCM8_MTYPE_ATTRIBUTE)
bank = 1;
else if ( mem_type == PCM8_MTYPE_IO)
bank = 2;
else
bank = 0; // This is an error
if (socket)
bank += 3;
return(bank);
}
void pcm860_wr_gcr(int socket, dword l)
{
if (socket == 0)
IMMR->pcmcia_pgcra = l;
else
IMMR->pcmcia_pgcrb = l;
}
dword pcm860_rd_gcr(int socket)
{
dword l;
if (socket == 0)
l = IMMR->pcmcia_pgcra;
else
l = IMMR->pcmcia_pgcrb;
return(l);
}
void pcm860_wr_option_reg(int reg, dword val)
{
switch (reg) {
case 0:
IMMR->pcmcia_por0 = val;
break;
case 1:
IMMR->pcmcia_por1 = val;
break;
case 2:
IMMR->pcmcia_por2 = val;
break;
case 3:
IMMR->pcmcia_por3 = val;
break;
case 4:
IMMR->pcmcia_por4 = val;
break;
case 5:
IMMR->pcmcia_por5 = val;
break;
case 6:
IMMR->pcmcia_por6 = val;
break;
case 7:
IMMR->pcmcia_por7 = val;
break;
}
}
void pcm860_wr_address_reg(int reg, dword val)
{
switch (reg) {
case 0:
IMMR->pcmcia_pbr0 = val;
break;
case 1:
IMMR->pcmcia_pbr1 = val;
break;
case 2:
IMMR->pcmcia_pbr2 = val;
break;
case 3:
IMMR->pcmcia_pbr3 = val;
break;
case 4:
IMMR->pcmcia_pbr4 = val;
break;
case 5:
IMMR->pcmcia_pbr5 = val;
break;
case 6:
IMMR->pcmcia_pbr6 = val;
break;
case 7:
IMMR->pcmcia_pbr7 = val;
break;
}
}
PFBYTE pcm860_map_window(int socket, int is_16, int mem_type)
{
dword cfg_word;
int window;
PFBYTE p;
window = pcm860_socket_to_bank(socket, mem_type);
cfg_word = pcmcia_bank_size[window];
cfg_word |= PCM8_STROBE;
if (is_16)
cfg_word |= PCM8_PPS16;
if (socket)
cfg_word |= PCM8_SLOTB;
cfg_word |= mem_type;
cfg_word |= PCM8_PV;
pcm860_wr_address_reg(window, pcmcia_bank_address[window]);
pcm860_wr_option_reg(window, cfg_word);
p = (PFBYTE) pcmcia_bank_address[window];
return(p);
}
#if (defined(ERTFS_SA))
void hook_pcmcia_interrupt(int irq);
#endif
BOOLEAN pcmctrl_initted;
BOOLEAN card_is_powered[NSOCKET];
int card_device_type[NSOCKET];
void ertfs_card_down(int slot)
{
#if (INCLUDE_ERTFS)
int j;
DDRIVE *pdr;
for (j = 0; j < NDRIVES; j++)
{
pdr = pc_drno_to_drive_struct(j);
if (pdr &&
pdr->drive_flags & DRIVE_FLAGS_PCMCIA &&
pdr->drive_flags & DRIVE_FLAGS_VALID &&
pdr->pcmcia_slot_number == slot &&
pdr->pcmcia_controller_number == 0)
{
pdr->dev_table_perform_device_ioctl(
pdr->driveno,
DEVCTL_REPORT_REMOVE, (PFVOID) 0);
map_slot_to_controller[slot] = -1;
}
}
#endif
}
void KS_FAR mgmt_isr(int arg) /*__fn__*/
{
dword xx;
xx = IMMR->pcmcia_pscr;
/* Card detect 1 or card detect 2 for Card A has changed ... */
if ( (xx & PSCR_CACD2_C) || (xx & PSCR_CACD1_C))
{
ertfs_card_down(0);
pcmctrl_card_down(0);
}
/* Card detect 1 or card detect 2 for Card B has changed ... */
if ( (xx & PSCR_CBCD2_C) || (xx & PSCR_CBCD1_C))
{
ertfs_card_down(1);
pcmctrl_card_down(1);
}
/* Clear all mgmt interrupts for slot A and B */
// IMMR->pcmcia_pscr = (PSCR_CACD2_C|PSCR_CACD1_C|PSCR_CBCD2_C|PSCR_CBCD1_C);
IMMR->pcmcia_pscr = PCMCIA_ALL_AMGMT|PCMCIA_ALL_BMGMT;
}
void pcmcia_irq_isr(void)
{
dword xx;
xx = IMMR->pcmcia_pscr;
/* IRQ for slot A/Card A has changed ... */
if ( xx & PCMCIA_ALL_AIRQ )
{
if( map_slot_to_controller[0] >= 0)
ide_isr(map_slot_to_controller[0]);
IMMR->pcmcia_pscr = PCMCIA_ALL_AIRQ;
}
/* IRQ for slot B/Card B has changed ... */
if ( xx & PCMCIA_ALL_BIRQ )
{
if( map_slot_to_controller[1] >= 0)
ide_isr(map_slot_to_controller[1]);
IMMR->pcmcia_pscr = PCMCIA_ALL_BIRQ;
}
}
BOOLEAN pcmctrl_init(void) /* __fn__ */
{
int i;
byte mask;
dword l;
if ( pcmctrl_initted )
return(TRUE);
ks_disable();
/* Make sure power is down on all sockets */
#if (FADS860)
{
dword *bcsr1 = at_bcsr1();
*bcsr1 |= PCMCIA_0V; /* 0 Level vcc */
*bcsr1 |= PCMCIA_HIZPP; /* High Impedence Voltage Level vpp */
/* Enable FADS PCMCIA Channel */
*bcsr1 &= ~PCCEN;
}
#elif (ADS860)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -