📄 ide-ics.c
字号:
/* * linux/arch/arm/drivers/block/ide-ics.c * * Copyright (c) 1996,1997 Russell King. * * Changelog: * 08-06-1996 RMK Created * 12-09-1997 RMK Added interrupt enable/disable */#include <linux/module.h>#include <linux/malloc.h>#include <linux/blkdev.h>#include <linux/errno.h>#include <asm/dma.h>#include <asm/ecard.h>#include <asm/io.h>#include "ide.h"/* * Maximum number of interfaces per card */#define MAX_IFS 2#define ICS_IDENT_OFFSET 0x8a0#define ICS_ARCIN_V5_INTRSTAT 0x000#define ICS_ARCIN_V5_INTROFFSET 0x001#define ICS_ARCIN_V5_IDEOFFSET 0xa00#define ICS_ARCIN_V5_IDEALTOFFSET 0xae0#define ICS_ARCIN_V5_IDESTEPPING 4#define ICS_ARCIN_V6_IDEOFFSET_1 0x800#define ICS_ARCIN_V6_INTROFFSET_1 0x880#define ICS_ARCIN_V6_INTRSTAT_1 0x8a4#define ICS_ARCIN_V6_IDEALTOFFSET_1 0x8e0#define ICS_ARCIN_V6_IDEOFFSET_2 0xc00#define ICS_ARCIN_V6_INTROFFSET_2 0xc80#define ICS_ARCIN_V6_INTRSTAT_2 0xca4#define ICS_ARCIN_V6_IDEALTOFFSET_2 0xce0#define ICS_ARCIN_V6_IDESTEPPING 4static const card_ids icside_cids[] = { { MANU_ICS, PROD_ICS_IDE }, { MANU_ICS2, PROD_ICS2_IDE }, { 0xffff, 0xffff }};typedef enum { ics_if_unknown, ics_if_arcin_v5, ics_if_arcin_v6} iftype_t;static struct expansion_card *ec[MAX_ECARDS];static int result[MAX_ECARDS][MAX_IFS];/* ---------------- Version 5 PCB Support Functions --------------------- *//* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) * Purpose : enable interrupts from card */static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr){ unsigned int memc_port = (unsigned int)ec->irq_data; outb (0, memc_port + ICS_ARCIN_V5_INTROFFSET);}/* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) * Purpose : disable interrupts from card */static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr){ unsigned int memc_port = (unsigned int)ec->irq_data; inb (memc_port + ICS_ARCIN_V5_INTROFFSET);}static const expansioncard_ops_t icside_ops_arcin_v5 = { icside_irqenable_arcin_v5, icside_irqdisable_arcin_v5, NULL, NULL, NULL, NULL};/* ---------------- Version 6 PCB Support Functions --------------------- *//* Prototype: icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) * Purpose : enable interrupts from card */static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr){ unsigned int ide_base_port = (unsigned int)ec->irq_data; outb (0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); outb (0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_2);}/* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) * Purpose : disable interrupts from card */static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr){ unsigned int ide_base_port = (unsigned int)ec->irq_data; inb (ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); inb (ide_base_port + ICS_ARCIN_V6_INTROFFSET_2);}/* Prototype: icside_irqprobe(struct expansion_card *ec) * Purpose : detect an active interrupt from card */static int icside_irqprobe_arcin_v6(struct expansion_card *ec){ unsigned int ide_base_port = (unsigned int)ec->irq_data; return inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;}static const expansioncard_ops_t icside_ops_arcin_v6 = { icside_irqenable_arcin_v6, icside_irqdisable_arcin_v6, icside_irqprobe_arcin_v6, NULL, NULL, NULL};/* Prototype: icside_identifyif (struct expansion_card *ec) * Purpose : identify IDE interface type * Notes : checks the description string */static iftype_t icside_identifyif (struct expansion_card *ec){ unsigned int addr; iftype_t iftype; int id = 0; iftype = ics_if_unknown; addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET; id = inb (addr) & 1; id |= (inb (addr + 1) & 1) << 1; id |= (inb (addr + 2) & 1) << 2; id |= (inb (addr + 3) & 1) << 3; switch (id) { case 0: /* A3IN */ printk ("icside: A3IN unsupported\n"); break; case 1: /* A3USER */ printk ("icside: A3USER unsupported\n"); break; case 3: /* ARCIN V6 */ printk ("icside: detected ARCIN V6 in slot %d\n", ec->slot_no); iftype = ics_if_arcin_v6; break; case 15:/* ARCIN V5 (no id) */ printk ("icside: detected ARCIN V5 in slot %d\n", ec->slot_no); iftype = ics_if_arcin_v5; break; default:/* we don't know - complain very loudly */ printk ("icside: ***********************************\n"); printk ("icside: *** UNKNOWN ICS INTERFACE id=%d ***\n", id); printk ("icside: ***********************************\n"); printk ("icside: please report this to: linux@arm.linux.org.uk\n"); break; } return iftype;}/* Prototype: icside_register (struct expansion_card *ec) * Purpose : register an ICS IDE card with the IDE driver * Notes : we make sure that interrupts are disabled from the card */static inline void icside_register (struct expansion_card *ec, int index){ unsigned long port = 0, latch; result[index][0] = -1; result[index][1] = -1; switch (icside_identifyif (ec)) { case ics_if_unknown: default: printk ("icside: *** Warning: ICS IDE Interface unrecognised! ***\n"); break; case ics_if_arcin_v5: port = ecard_address (ec, ECARD_MEMC, 0); ec->irqaddr = (unsigned char *)ioaddr(port + ICS_ARCIN_V5_INTRSTAT); ec->irqmask = 1; ec->irq_data = (void *)port; ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5; /* * Be on the safe side - disable interrupts */ inb (port + ICS_ARCIN_V5_INTROFFSET); result[index][0] = ide_register_port(port + ICS_ARCIN_V5_IDEOFFSET, port + ICS_ARCIN_V5_IDEALTOFFSET, ICS_ARCIN_V5_IDESTEPPING, ec->irq); break; case ics_if_arcin_v6: latch = ecard_address (ec, ECARD_IOC, ECARD_FAST); if (ec->dma == NO_DMA) port = ecard_address (ec, ECARD_EASI, ECARD_FAST); if (port) outb(0x20, latch); else { port = latch; outb(0, port); } ec->irq_data = (void *)port; ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6; /* * Be on the safe side - disable interrupts */ inb (port + ICS_ARCIN_V6_INTROFFSET_1); inb (port + ICS_ARCIN_V6_INTROFFSET_2); result[index][0] = ide_register_port(port + ICS_ARCIN_V6_IDEOFFSET_1, port + ICS_ARCIN_V6_IDEALTOFFSET_1, ICS_ARCIN_V6_IDESTEPPING, ec->irq); result[index][1] = ide_register_port(port + ICS_ARCIN_V6_IDEOFFSET_2, port + ICS_ARCIN_V6_IDEALTOFFSET_2, ICS_ARCIN_V6_IDESTEPPING, ec->irq); break; } }int icside_init (void){ int i; for (i = 0; i < MAX_ECARDS; i++) ec[i] = NULL; ecard_startfind (); for (i = 0; ; i++) { if ((ec[i] = ecard_find (0, icside_cids)) == NULL) break; ecard_claim (ec[i]); icside_register (ec[i], i); } for (i = 0; i < MAX_ECARDS; i++) if (ec[i] && result[i][0] < 0 && result[i][1] < 0) { ecard_release (ec[i]); ec[i] = NULL; } return 0;}#ifdef MODULEint init_module (void){ return icside_init();}void cleanup_module (void){ int i; for (i = 0; i < MAX_ECARDS; i++) if (ec[i]) { if (result[i][0] >= 0) ide_unregister (result[i][0]); if (result[i][1] >= 0) ide_unregister (result[i][1]); ecard_release (ec[i]); ec[i] = NULL; }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -