📄 pcmcia_core.c
字号:
#include <target/io.h>#include <target/herrno.h>#include <target/htypes.h>#include <target/memzero.h>#include "pcmcia_core.h"#define CORE_NAME "pcmcia_core"#undef DEBUG#if defined(DEBUG)#define DEBUG_FUNC() hprintf("*" CORE_NAME ": %s()\n", __FUNCTION__)#define DEBUG_INFO(args...) hprintf("*" CORE_NAME ": " args)#define DEBUG_ERR(args...) hprintf("*" CORE_NAME ": " args)#define DEBUG_RAW(args...) hprintf(args)#define DEBUG_DUMP_CIS#else#define DEBUG_FUNC()#define DEBUG_INFO(args...)#define DEBUG_ERR(args...)#define DEBUG_RAW(args...)#undef DEBUG_DUMP_CIS#endif#define PRINT_INFO(args...) hprintf(CORE_NAME ": " args)#define PRINT_ERR(args...) hprintf(CORE_NAME ": " args)#define PRINT_RAW(args...) hprintf(args)#define CCR_CCOR (0)#define CCR_CCSR (2)#define CCR_PRR (4)#define CCR_SCR (6)#define GET_CIS(o) ((u8)(pcmcia_inw(info->attr_base + ((o) << 1)) & 0xff))#define CIS_MAX_LEN 0x200#define SET_CCR(o, v) (pcmcia_outb(info->attr_base + ccr_base + (o), (v)))#define GET_CCR(o) (pcmcia_inb(info->attr_base + ccr_base + (o)))static pcmcia_info_t pcmcia_info;static pcmcia_ops_t *_pcmcia_ops;/**************************************************************************** * ****************************************************************************/static inline u8pcmcia_inb(u32 addr){ return *(volatile u8 *)addr;}/**************************************************************************** * ****************************************************************************/static inline u16pcmcia_inw(u32 addr){ return *(volatile u16 *)addr;}/**************************************************************************** * ****************************************************************************/static inline voidpcmcia_outb(u32 addr, u8 val){ *(volatile u8 *)addr = val;}/**************************************************************************** * ****************************************************************************/static inline voidpcmcia_outw(u32 addr, u16 val){ *(volatile u16 *)addr = val;}/**************************************************************************** * ****************************************************************************/static intpcmcia_register_ops(pcmcia_ops_t *ops){ if(_pcmcia_ops) return -H_EINVAL; _pcmcia_ops = ops; return 0;}/**************************************************************************** * ****************************************************************************/static voidpcmcia_unregister_ops(void){ _pcmcia_ops = NULL;}/**************************************************************************** * ****************************************************************************/static pcmcia_ops_t *pcmcia_get_ops(void){ return _pcmcia_ops;}/**************************************************************************** * ****************************************************************************/#if defined(DEBUG_DUMP_CIS)static voidpcmcia_dump_cis(pcmcia_info_t *info){ u32 ptr = 0; int i; DEBUG_FUNC(); while (ptr < CIS_MAX_LEN) { u8 code, len; if (GET_CIS(ptr) == 0xff) break; code = GET_CIS(ptr++); len = GET_CIS(ptr++); DEBUG_INFO("Code: %bh, Len: %bh\n\t", code, len); for (i=0; i<len; i++) { DEBUG_RAW("%b ", GET_CIS(ptr++)); if (i % 16 == 15) DEBUG_RAW("\n\t"); } DEBUG_RAW("\n"); }}#else#define pcmcia_dump_cis(info)#endif/**************************************************************************** * ****************************************************************************/static intpcmcia_search_tuple(pcmcia_info_t *info, u8 tuple_code){ u32 ptr = 0; DEBUG_FUNC(); while (ptr < CIS_MAX_LEN) { u8 code, len; if (GET_CIS(ptr) == 0xff) return -1;/* Can't find */ if (tuple_code == GET_CIS(ptr)) return ptr; code = GET_CIS(ptr++); len = GET_CIS(ptr++); ptr += len; } return 0;}/**************************************************************************** * ****************************************************************************/static intpcmcia_print_card_info(pcmcia_info_t *info){ u32 ptr; u8 code, len, ver[2]; int i; ptr = pcmcia_search_tuple(info, 0x15); if (ptr < 0) return -H_EIO; code = GET_CIS(ptr++); len = GET_CIS(ptr++); ver[0] = GET_CIS(ptr++); ver[1] = GET_CIS(ptr++); PRINT_INFO("Disk drive detected: \n\tModel: "); for (i=0; i<len-2; i++) { u8 c = GET_CIS(ptr++); if (c == 0xff) break; if (c < 0x20) continue; PRINT_RAW("%c", c); } PRINT_RAW("\n"); return 0;}/**************************************************************************** * ****************************************************************************/static intpcmcia_get_funcid(pcmcia_info_t *info){ u32 ptr; DEBUG_FUNC(); ptr = pcmcia_search_tuple(info, 0x21); if (ptr < 0) return -H_EIO; return (u32)GET_CIS(ptr + 2);}/**************************************************************************** * ****************************************************************************/static intpcmcia_config_device(pcmcia_info_t *info){ pcmcia_ops_t *ops; u32 ptr; u8 size; u32 ccr_base = 0; int i; DEBUG_FUNC(); ptr = pcmcia_search_tuple(info, 0x1a); if (ptr < 0) return -H_EIO; size = (GET_CIS(ptr + 2) & 0x3) + 1; for (i=0; i<size; i++) ccr_base |= (GET_CIS(ptr + 4 + i) << (8 * i)); DEBUG_INFO("ccr_base: %p\n", ccr_base); /* set level mode irq and I/O mapped device in config reg */ SET_CCR(CCR_SCR, 0x00); SET_CCR(CCR_CCOR, 0x41); SET_CCR(CCR_CCSR, 0x00); SET_CCR(CCR_PRR, 0x00); DEBUG_INFO("SCR:%b, CCOR:%b, CCSR:%b, PRR:%b\n", GET_CCR(CCR_SCR), GET_CCR(CCR_CCOR), GET_CCR(CCR_CCSR), GET_CCR(CCR_PRR)); ops = pcmcia_get_ops(); if (!ops->set_io_map) return -H_EINVAL; ops->set_io_map(1/*IO*/); return 0;}/**************************************************************************** * ****************************************************************************/intpcmcia_probe(void *priv){ pcmcia_ops_t *ops = (pcmcia_ops_t *)priv; int ret; DEBUG_FUNC(); /* registration ops */ if (!ops) return -H_EINVAL; if (!ops->set_socket) return -H_EINVAL; if (!ops->get_status) return -H_EINVAL; pcmcia_register_ops(ops); memzero(&pcmcia_info, sizeof(pcmcia_info_t)); if (ops->hw_init) { ret = ops->hw_init(&pcmcia_info); if (ret < 0) return ret; } ops->set_socket(1); ret = ops->get_status(); if (ret < 0) return -H_EIO; ops->set_mem_map(1/*ATTR*/); ret = pcmcia_get_funcid(&pcmcia_info); if (ret != 0x04) return -H_EIO; pcmcia_dump_cis(&pcmcia_info); pcmcia_print_card_info(&pcmcia_info); pcmcia_config_device(&pcmcia_info); return 0;}/**************************************************************************** * ****************************************************************************/voidpcmcia_remove(void *priv){ pcmcia_ops_t *ops = (pcmcia_ops_t *)priv; DEBUG_FUNC(); pcmcia_unregister_ops(); if (!ops) return; if (ops->hw_free) ops->hw_free();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -