/* * platform.c: handling x86 platform related MMIO instructions * * Copyright (c) 2004, Intel Corporation. * Copyright (c) 2005, International Business Machines Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DECODE_success 1 #define DECODE_failure 0 #define mk_operand(size_reg, index, seg, flag) \ (((size_reg) << 24) | ((index) << 16) | ((seg) << 8) | (flag)) #if defined (__x86_64__) static inline long __get_reg_value(unsigned long reg, int size) { switch ( size ) { case BYTE_64: return (char)(reg & 0xFF); case WORD: return (short)(reg & 0xFFFF); case LONG: return (int)(reg & 0xFFFFFFFF); case QUAD: return (long)(reg); default: printk("Error: (__get_reg_value) Invalid reg size\n"); domain_crash_synchronous(); } } long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs) { if ( size == BYTE ) { switch ( index ) { case 0: /* %al */ return (char)(regs->rax & 0xFF); case 1: /* %cl */ return (char)(regs->rcx & 0xFF); case 2: /* %dl */ return (char)(regs->rdx & 0xFF); case 3: /* %bl */ return (char)(regs->rbx & 0xFF); case 4: /* %ah */ return (char)((regs->rax & 0xFF00) >> 8); case 5: /* %ch */ return (char)((regs->rcx & 0xFF00) >> 8); case 6: /* %dh */ return (char)((regs->rdx & 0xFF00) >> 8); case 7: /* %bh */ return (char)((regs->rbx & 0xFF00) >> 8); default: printk("Error: (get_reg_value) Invalid index value\n"); domain_crash_synchronous(); } /* NOTREACHED */ } switch ( index ) { case 0: return __get_reg_value(regs->rax, size); case 1: return __get_reg_value(regs->rcx, size); case 2: return __get_reg_value(regs->rdx, size); case 3: return __get_reg_value(regs->rbx, size); case 4: return __get_reg_value(regs->rsp, size); case 5: return __get_reg_value(regs->rbp, size); case 6: return __get_reg_value(regs->rsi, size); case 7: return __get_reg_value(regs->rdi, size); case 8: return __get_reg_value(regs->r8, size); case 9: return __get_reg_value(regs->r9, size); case 10: return __get_reg_value(regs->r10, size); case 11: return __get_reg_value(regs->r11, size); case 12: return __get_reg_value(regs->r12, size); case 13: return __get_reg_value(regs->r13, size); case 14: return __get_reg_value(regs->r14, size); case 15: return __get_reg_value(regs->r15, size); default: printk("Error: (get_reg_value) Invalid index value\n"); domain_crash_synchronous(); } } #elif defined (__i386__) static inline long __get_reg_value(unsigned long reg, int size) { switch ( size ) { case WORD: return (short)(reg & 0xFFFF); case LONG: return (int)(reg & 0xFFFFFFFF); default: printk("Error: (__get_reg_value) Invalid reg size\n"); domain_crash_synchronous(); } } long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs) { if ( size == BYTE ) { switch ( index ) { case 0: /* %al */ return (char)(regs->eax & 0xFF); case 1: /* %cl */ return (char)(regs->ecx & 0xFF); case 2: /* %dl */ return (char)(regs->edx & 0xFF); case 3: /* %bl */ return (char)(regs->ebx & 0xFF); case 4: /* %ah */ return (char)((regs->eax & 0xFF00) >> 8); case 5: /* %ch */ return (char)((regs->ecx & 0xFF00) >> 8); case 6: /* %dh */ return (char)((regs->edx & 0xFF00) >> 8); case 7: /* %bh */ return (char)((regs->ebx & 0xFF00) >> 8); default: printk("Error: (get_reg_value) Invalid index value\n"); domain_crash_synchronous(); } } switch ( index ) { case 0: return __get_reg_value(regs->eax, size); case 1: return __get_reg_value(regs->ecx, size); case 2: return __get_reg_value(regs->edx, size); case 3: return __get_reg_value(regs->ebx, size); case 4: return __get_reg_value(regs->esp, size); case 5: return __get_reg_value(regs->ebp, size); case 6: return __get_reg_value(regs->esi, size); case 7: return __get_reg_value(regs->edi, size); default: printk("Error: (get_reg_value) Invalid index value\n"); domain_crash_synchronous(); } } #endif static inline unsigned char *check_prefix(unsigned char *inst, struct hvm_io_op *mmio_op, unsigned char *ad_size, unsigned char *op_size, unsigned char *seg_sel, unsigned char *rex_p) { while ( 1 ) { switch ( *inst ) { /* rex prefix for em64t instructions */ case 0x40 ... 0x4f: *rex_p = *inst; break; case 0xf3: /* REPZ */ mmio_op->flags = REPZ; break; case 0xf2: /* REPNZ */ mmio_op->flags = REPNZ; break; case 0xf0: /* LOCK */ break; case 0x2e: /* CS */ case 0x36: /* SS */ case 0x3e: /* DS */ case 0x26: /* ES */ case 0x64: /* FS */ case 0x65: /* GS */ *seg_sel = *inst; break; case 0x66: /* 32bit->16bit */ *op_size = WORD; break; case 0x67: *ad_size = WORD; break; default: return inst; } inst++; } } static inline unsigned long get_immediate(int ad_size, const unsigned char *inst, int op_size) { int mod, reg, rm; unsigned long val = 0; int i; mod = (*inst >> 6) & 3; reg = (*inst >> 3) & 7; rm = *inst & 7; inst++; //skip ModR/M byte if ( ad_size != WORD && mod != 3 && rm == 4 ) { rm = *inst & 7; inst++; //skip SIB byte } switch ( mod ) { case 0: if ( ad_size == WORD ) { if ( rm == 6 ) inst = inst + 2; //disp16, skip 2 bytes } else { if ( rm == 5 ) inst = inst + 4; //disp32, skip 4 bytes } break; case 1: inst++; //disp8, skip 1 byte break; case 2: if ( ad_size == WORD ) inst = inst + 2; //disp16, skip 2 bytes else inst = inst + 4; //disp32, skip 4 bytes break; } if ( op_size == QUAD ) op_size = LONG; for ( i = 0; i < op_size; i++ ) { val |= (*inst++ & 0xff) << (8 * i); } return val; } static inline int get_index(const unsigned char *inst, unsigned char rex) { int mod, reg, rm; int rex_r, rex_b; mod = (*inst >> 6) & 3; reg = (*inst >> 3) & 7; rm = *inst & 7; rex_r = (rex >> 2) & 1; rex_b = rex & 1; //Only one operand in the instruction is register if ( mod == 3 ) { return (rm + (rex_b << 3)); } else { return (reg + (rex_r << 3)); } return 0; } static void init_instruction(struct hvm_io_op *mmio_op) { mmio_op->instr = 0; mmio_op->flags = 0; mmio_op->operand[0] = 0; mmio_op->operand[1] = 0; mmio_op->immediate = 0; } #define GET_OP_SIZE_FOR_BYTE(size_reg) \ do { \ if ( rex ) \ (size_reg) = BYTE_64; \ else \ (size_reg) = BYTE; \ } while( 0 ) #define GET_OP_SIZE_FOR_NONEBYTE(op_size) \ do { \ if ( rex & 0x8 ) \ (op_size) = QUAD; \ else if ( (op_size) != WORD ) \ (op_size) = LONG; \ } while( 0 ) /* * Decode mem,accumulator operands (as in m8/m16/m32, al,ax,eax) */ static inline int mem_acc(unsigned char size, struct hvm_io_op *mmio) { mmio->operand[0] = mk_operand(size, 0, 0, MEMORY); mmio->operand[1] = mk_operand(size, 0, 0, REGISTER); return DECODE_success; } /* * Decode accumulator,mem operands (as in al,ax,eax, m8/m16/m32) */ static inline int acc_mem(unsigned char size, struct hvm_io_op *mmio) { mmio->operand[0] = mk_operand(size, 0, 0, REGISTER); mmio->operand[1] = mk_operand(size, 0, 0, MEMORY); return DECODE_success; } /* * Decode mem,reg operands (as in r32/16, m32/16) */ static int mem_reg(unsigned char size, unsigned char *opcode, struct hvm_io_op *mmio_op, unsigned char rex) { int index = get_index(opcode + 1, rex); mmio_op->operand[0] = mk_operand(size, 0, 0, MEMORY); mmio_op->operand[1] = mk_operand(size, index, 0, REGISTER); return DECODE_success; } /* * Decode reg,mem operands (as in m32/16, r32/16) */ static int reg_mem(unsigned char size, unsigned char *opcode, struct hvm_io_op *mmio_op, unsigned char rex) { int index = get_index(opcode + 1, rex); mmio_op->operand[0] = mk_operand(size, index, 0, REGISTER); mmio_op->operand[1] = mk_operand(size, 0, 0, MEMORY); return DECODE_success; } static int mmio_decode(int address_bytes, unsigned char *opcode, struct hvm_io_op *mmio_op, unsigned char *ad_size, unsigned char *op_size, unsigned char *seg_sel) { unsigned char size_reg = 0; unsigned char rex = 0; int index; *ad_size = 0; *op_size = 0; *seg_sel = 0; init_instruction(mmio_op); opcode = check_prefix(opcode, mmio_op, ad_size, op_size, seg_sel, &rex); switch ( address_bytes ) { case 2: if ( *op_size == WORD ) *op_size = LONG; else if ( *op_size == LONG ) *op_size = WORD; else if ( *op_size == 0 ) *op_size = WORD; if ( *ad_size == WORD ) *ad_size = LONG; else if ( *ad_size == LONG ) *ad_size = WORD; else if ( *ad_size == 0 ) *ad_size = WORD; break; case 4: if ( *op_size == 0 ) *op_size = LONG; if ( *ad_size == 0 ) *ad_size = LONG; break; #ifdef __x86_64__ case 8: if ( *op_size == 0 ) *op_size = rex & 0x8 ? QUAD : LONG; if ( *ad_size == 0 ) *ad_size = QUAD; break; #endif } /* the operands order in comments conforms to AT&T convention */ switch ( *opcode ) { case 0x00: /* add r8, m8 */ mmio_op->instr = INSTR_ADD; *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); return reg_mem(size_reg, opcode, mmio_op, rex); case 0x03: /* add m32/16, r32/16 */ mmio_op->instr = INSTR_ADD; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return mem_reg(*op_size, opcode, mmio_op, rex); case 0x0A: /* or m8, r8 */ mmio_op->instr = INSTR_OR; *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); return mem_reg(size_reg, opcode, mmio_op, rex); case 0x0B: /* or m32/16, r32/16 */ mmio_op->instr = INSTR_OR; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return mem_reg(*op_size, opcode, mmio_op, rex); case 0x20: /* and r8, m8 */ mmio_op->instr = INSTR_AND; *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); return reg_mem(size_reg, opcode, mmio_op, rex); case 0x21: /* and r32/16, m32/16 */ mmio_op->instr = INSTR_AND; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return reg_mem(*op_size, opcode, mmio_op, rex); case 0x22: /* and m8, r8 */ mmio_op->instr = INSTR_AND; *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); return mem_reg(size_reg, opcode, mmio_op, rex); case 0x23: /* and m32/16, r32/16 */ mmio_op->instr = INSTR_AND; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return mem_reg(*op_size, opcode, mmio_op, rex); case 0x2B: /* sub m32/16, r32/16 */ mmio_op->instr = INSTR_SUB; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return mem_reg(*op_size, opcode, mmio_op, rex); case 0x30: /* xor r8, m8 */ mmio_op->instr = INSTR_XOR; *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); return reg_mem(size_reg, opcode, mmio_op, rex); case 0x31: /* xor r32/16, m32/16 */ mmio_op->instr = INSTR_XOR; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return reg_mem(*op_size, opcode, mmio_op, rex); case 0x32: /* xor m8, r8 */ mmio_op->instr = INSTR_XOR; *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); return mem_reg(size_reg, opcode, mmio_op, rex); case 0x38: /* cmp r8, m8 */ mmio_op->instr = INSTR_CMP; *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); return reg_mem(size_reg, opcode, mmio_op, rex); case 0x39: /* cmp r32/16, m32/16 */ mmio_op->instr = INSTR_CMP; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return reg_mem(*op_size, opcode, mmio_op, rex); case 0x3A: /* cmp m8, r8 */ mmio_op->instr = INSTR_CMP; *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); return mem_reg(size_reg, opcode, mmio_op, rex); case 0x3B: /* cmp m32/16, r32/16 */ mmio_op->instr = INSTR_CMP; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return mem_reg(*op_size, opcode, mmio_op, rex); case 0x80: case 0x81: case 0x83: { unsigned char ins_subtype = (opcode[1] >> 3) & 7; if ( opcode[0] == 0x80 ) { *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); } else { GET_OP_SIZE_FOR_NONEBYTE(*op_size); size_reg = *op_size; } /* opcode 0x83 always has a single byte operand */ if ( opcode[0] == 0x83 ) mmio_op->immediate = (signed char)get_immediate(*ad_size, opcode + 1, BYTE); else mmio_op->immediate = get_immediate(*ad_size, opcode + 1, *op_size); mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE); mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY); switch ( ins_subtype ) { case 0: /* add $imm, m32/16 */ mmio_op->instr = INSTR_ADD; return DECODE_success; case 1: /* or $imm, m32/16 */ mmio_op->instr = INSTR_OR; return DECODE_success; case 4: /* and $imm, m32/16 */ mmio_op->instr = INSTR_AND; return DECODE_success; case 5: /* sub $imm, m32/16 */ mmio_op->instr = INSTR_SUB; return DECODE_success; case 6: /* xor $imm, m32/16 */ mmio_op->instr = INSTR_XOR; return DECODE_success; case 7: /* cmp $imm, m32/16 */ mmio_op->instr = INSTR_CMP; return DECODE_success; default: printk("%x/%x, This opcode isn't handled yet!\n", *opcode, ins_subtype); return DECODE_failure; } } case 0x84: /* test r8, m8 */ mmio_op->instr = INSTR_TEST; *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); return reg_mem(size_reg, opcode, mmio_op, rex); case 0x85: /* test r16/32, m16/32 */ mmio_op->instr = INSTR_TEST; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return reg_mem(*op_size, opcode, mmio_op, rex); case 0x86: /* xchg m8, r8 */ mmio_op->instr = INSTR_XCHG; *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); return reg_mem(size_reg, opcode, mmio_op, rex); case 0x87: /* xchg m16/32, r16/32 */ mmio_op->instr = INSTR_XCHG; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return reg_mem(*op_size, opcode, mmio_op, rex); case 0x88: /* mov r8, m8 */ mmio_op->instr = INSTR_MOV; *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); return reg_mem(size_reg, opcode, mmio_op, rex); case 0x89: /* mov r32/16, m32/16 */ mmio_op->instr = INSTR_MOV; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return reg_mem(*op_size, opcode, mmio_op, rex); case 0x8A: /* mov m8, r8 */ mmio_op->instr = INSTR_MOV; *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); return mem_reg(size_reg, opcode, mmio_op, rex); case 0x8B: /* mov m32/16, r32/16 */ mmio_op->instr = INSTR_MOV; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return mem_reg(*op_size, opcode, mmio_op, rex); case 0xA0: /* mov , al */ mmio_op->instr = INSTR_MOV; *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); return mem_acc(size_reg, mmio_op); case 0xA1: /* mov , ax/eax */ mmio_op->instr = INSTR_MOV; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return mem_acc(*op_size, mmio_op); case 0xA2: /* mov al, */ mmio_op->instr = INSTR_MOV; *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); return acc_mem(size_reg, mmio_op); case 0xA3: /* mov ax/eax, */ mmio_op->instr = INSTR_MOV; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return acc_mem(*op_size, mmio_op); case 0xA4: /* movsb */ mmio_op->instr = INSTR_MOVS; *op_size = BYTE; return DECODE_success; case 0xA5: /* movsw/movsl */ mmio_op->instr = INSTR_MOVS; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return DECODE_success; case 0xAA: /* stosb */ mmio_op->instr = INSTR_STOS; *op_size = BYTE; return DECODE_success; case 0xAB: /* stosw/stosl */ mmio_op->instr = INSTR_STOS; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return DECODE_success; case 0xAC: /* lodsb */ mmio_op->instr = INSTR_LODS; *op_size = BYTE; return DECODE_success; case 0xAD: /* lodsw/lodsl */ mmio_op->instr = INSTR_LODS; GET_OP_SIZE_FOR_NONEBYTE(*op_size); return DECODE_success; case 0xC6: if ( ((opcode[1] >> 3) & 7) == 0 ) { /* mov $imm8, m8 */ mmio_op->instr = INSTR_MOV; *op_size = BYTE; mmio_op->operand[0] = mk_operand(*op_size, 0, 0, IMMEDIATE); mmio_op->immediate = get_immediate(*ad_size, opcode + 1, *op_size); mmio_op->operand[1] = mk_operand(*op_size, 0, 0, MEMORY); return DECODE_success; } else return DECODE_failure; case 0xC7: if ( ((opcode[1] >> 3) & 7) == 0 ) { /* mov $imm16/32, m16/32 */ mmio_op->instr = INSTR_MOV; GET_OP_SIZE_FOR_NONEBYTE(*op_size); mmio_op->operand[0] = mk_operand(*op_size, 0, 0, IMMEDIATE); mmio_op->immediate = get_immediate(*ad_size, opcode + 1, *op_size); mmio_op->operand[1] = mk_operand(*op_size, 0, 0, MEMORY); return DECODE_success; } else return DECODE_failure; case 0xF6: case 0xF7: if ( ((opcode[1] >> 3) & 7) == 0 ) { /* test $imm8/16/32, m8/16/32 */ mmio_op->instr = INSTR_TEST; if ( opcode[0] == 0xF6 ) { *op_size = BYTE; GET_OP_SIZE_FOR_BYTE(size_reg); } else { GET_OP_SIZE_FOR_NONEBYTE(*op_size); size_reg = *op_size; } mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE); mmio_op->immediate = get_immediate(*ad_size, opcode + 1, *op_size); mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
#
# Copyright (C) 2006-2012 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

BLOCK_MENU:=Block Devices

define KernelPackage/aoe
  SUBMENU:=$(BLOCK_MENU)
  TITLE:=ATA over Ethernet support
  KCONFIG:=CONFIG_ATA_OVER_ETH
  FILES:=$(LINUX_DIR)/drivers/block/aoe/aoe.ko
  AUTOLOAD:=$(call AutoLoad,30,aoe)
endef

define KernelPackage/aoe/description
 Kernel support for ATA over Ethernet
endef

$(eval $(call KernelPackage,aoe))


define KernelPackage/ata-core
  SUBMENU:=$(BLOCK_MENU)
  TITLE:=Serial and Parallel ATA support
  DEPENDS:=@PCI_SUPPORT||TARGET_sunxi +kmod-scsi-core
  KCONFIG:=CONFIG_ATA
  FILES:=$(LINUX_DIR)/drivers/ata/libata.ko
ifneq ($(wildcard $(LINUX_DIR)/drivers/ata/libahci.ko),)
  FILES+=$(LINUX_DIR)/drivers/ata/libahci.ko
endif
endef

$(eval $(call KernelPackage,ata-core))


define AddDepends/ata
  SUBMENU:=$(BLOCK_MENU)
  DEPENDS+=kmod-ata-core $(1)
endef


define KernelPackage/ata-ahci
  TITLE:=AHCI Serial ATA support
  KCONFIG:=CONFIG_SATA_AHCI
  FILES:= \
    $(LINUX_DIR)/drivers/ata/ahci.ko
  AUTOLOAD:=$(call AutoLoad,41,libahci ahci,1)
  $(call AddDepends/ata)
endef

define KernelPackage/ata-ahci/description
 Support for AHCI Serial ATA controllers
endef

$(eval $(call KernelPackage,ata-ahci))


define KernelPackage/ata-ahci-platform
  TITLE:=AHCI Serial ATA Platform support
  KCONFIG:=CONFIG_SATA_AHCI_PLATFORM
  FILES:= \
    $(LINUX_DIR)/drivers/ata/ahci_platform.ko \
    $(LINUX_DIR)/drivers/ata/libahci_platform.ko
  AUTOLOAD:=$(call AutoLoad,40,libahci libahci_platform ahci_platform,1)
  $(call AddDepends/ata,@TARGET_ipq806x||TARGET_sunxi)
endef

define KernelPackage/ata-ahci-platform/description
 Platform support for AHCI Serial ATA controllers
endef

$(eval $(call KernelPackage,ata-ahci-platform))


define KernelPackage/ata-artop
  TITLE:=ARTOP 6210/6260 PATA support
  KCONFIG:=CONFIG_PATA_ARTOP
  FILES:=$(LINUX_DIR)/drivers/ata/pata_artop.ko
  AUTOLOAD:=$(call AutoLoad,41,pata_artop,1)
  $(call AddDepends/ata)
endef

define KernelPackage/ata-artop/description
 PATA support for ARTOP 6210/6260 host controllers
endef

$(eval $(call KernelPackage,ata-artop))


define KernelPackage/ata-marvell-sata
  TITLE:=Marvell Serial ATA support
  KCONFIG:=CONFIG_SATA_MV
  FILES:=$(LINUX_DIR)/drivers/ata/sata_mv.ko
  AUTOLOAD:=$(call AutoLoad,41,sata_mv,1)
  $(call AddDepends/ata)
endef

define KernelPackage/ata-marvell-sata/description
 SATA support for marvell chipsets
endef

$(eval $(call KernelPackage,ata-marvell-sata))


define KernelPackage/ata-nvidia-sata
  TITLE:=Nvidia Serial ATA support
  KCONFIG:=CONFIG_SATA_NV
  FILES:=$(LINUX_DIR)/drivers/ata/sata_nv.ko
  AUTOLOAD:=$(call AutoLoad,41,sata_nv,1)
  $(call AddDepends/ata)
endef

$(eval $(call KernelPackage,ata-nvidia-sata))


define KernelPackage/ata-pdc202xx-old
  SUBMENU:=$(BLOCK_MENU)
  TITLE:=Older Promise PATA controller support
  DEPENDS:=kmod-ata-core
  KCONFIG:= \
       CONFIG_ATA_SFF=y \
       CONFIG_PATA_PDC_OLD
  FILES:=$(LINUX_DIR)/drivers/ata/pata_pdc202xx_old.ko
  AUTOLOAD:=$(call AutoLoad,41,pata_pdc202xx_old,1)
endef

define KernelPackage/ata-pdc202xx-old/description
 This option enables support for the Promise 20246, 20262, 20263,
 20265 and 20267 adapters
endef

$(eval $(call KernelPackage,ata-pdc202xx-old))


define KernelPackage/ata-piix
  TITLE:=Intel PIIX PATA/SATA support
  KCONFIG:=CONFIG_ATA_PIIX
  FILES:=$(LINUX_DIR)/drivers/ata/ata_piix.ko
  AUTOLOAD:=$(call AutoLoad,41,ata_piix,1)
  $(call AddDepends/ata)
endef

define KernelPackage/ata-piix/description
 SATA support for Intel ICH5/6/7/8 series host controllers and
 PATA support for Intel ESB/ICH/PIIX3/PIIX4 series host controllers
endef

$(eval $(call KernelPackage,ata-piix))


define KernelPackage/ata-sil
  TITLE:=Silicon Image SATA support
  KCONFIG:=CONFIG_SATA_SIL
  FILES:=$(LINUX_DIR)/drivers/ata/sata_sil.ko
  AUTOLOAD:=$(call AutoLoad,41,sata_sil,1)
  $(call AddDepends/ata)
endef

define KernelPackage/ata-sil/description
 Support for Silicon Image Serial ATA controllers
endef

$(eval $(call KernelPackage,ata-sil))


define KernelPackage/ata-sil24
  TITLE:=Silicon Image 3124/3132 SATA support
  KCONFIG:=CONFIG_SATA_SIL24
  FILES:=$(LINUX_DIR)/drivers/ata/sata_sil24.ko
  AUTOLOAD:=$(call AutoLoad,41,sata_sil24,1)
  $(call AddDepends/ata)
endef

define KernelPackage/ata-sil24/description
 Support for Silicon Image 3124/3132 Serial ATA controllers
endef

$(eval $(call KernelPackage,ata-sil24))


define KernelPackage/ata-via-sata
  TITLE:=VIA SATA support
  KCONFIG:=CONFIG_SATA_VIA
  FILES:=$(LINUX_DIR)/drivers/ata/sata_via.ko
  AUTOLOAD:=$(call AutoLoad,41,sata_via,1)
  $(call AddDepends/ata)
endef

define KernelPackage/ata-via-sata/description
 This option enables support for VIA Serial ATA
endef

$(eval $(call KernelPackage,ata-via-sata))


define KernelPackage/block2mtd
  SUBMENU:=$(BLOCK_MENU)
  TITLE:=Block device MTD emulation
  KCONFIG:=CONFIG_MTD_BLOCK2MTD
  FILES:=$(LINUX_DIR)/drivers/mtd/devices/block2mtd.ko
endef

$(eval $(call KernelPackage,block2mtd))


define KernelPackage/dm
  SUBMENU:=$(BLOCK_MENU)
  TITLE:=Device Mapper
  DEPENDS:=+kmod-crypto-manager
  # All the "=n" are unnecessary, they're only there
  # to stop the config from asking the question.
  # MIRROR is M because I've needed it for pvmove.
  KCONFIG:= \
	CONFIG_BLK_DEV_MD=n \
	CONFIG_DM_DEBUG=n \
	CONFIG_DM_UEVENT=n \
	CONFIG_DM_DELAY=n \
	CONFIG_DM_LOG_WRITES=n \
	CONFIG_DM_MQ_DEFAULT=n \
	CONFIG_DM_MULTIPATH=n \
	CONFIG_DM_ZERO=n \
	CONFIG_DM_SNAPSHOT=n \
	CONFIG_DM_LOG_USERSPACE=n \
	CONFIG_MD=y \
	CONFIG_BLK_DEV_DM \
	CONFIG_DM_CRYPT \
	CONFIG_DM_MIRROR
  FILES:=$(LINUX_DIR)/drivers/md/dm-*.ko
  AUTOLOAD:=$(call AutoLoad,30,dm-mod dm-log dm-region-hash dm-mirror dm-crypt)
endef

define KernelPackage/dm/description
 Kernel module necessary for LVM2 support
endef

$(eval $(call KernelPackage,dm))


define KernelPackage/md-mod
  SUBMENU:=$(BLOCK_MENU)
  TITLE:=MD RAID
  KCONFIG:= \
       CONFIG_MD=y \
       CONFIG_BLK_DEV_MD=m \
       CONFIG_MD_AUTODETECT=y \
       CONFIG_MD_FAULTY=n
  FILES:=$(LINUX_DIR)/drivers/md/md-mod.ko
  AUTOLOAD:=$(call AutoLoad,27,md-mod)
endef

define KernelPackage/md-mod/description
 Kernel RAID md module (md-mod.ko).
 You will need to select at least one RAID level module below.
endef

$(eval $(call KernelPackage,md-mod))


define KernelPackage/md/Depends
  SUBMENU:=$(BLOCK_MENU)
  DEPENDS:=kmod-md-mod $(1)
endef


define KernelPackage/md-linear
$(call KernelPackage/md/Depends,)
  TITLE:=RAID Linear Module
  KCONFIG:=CONFIG_MD_LINEAR
  FILES:=$(LINUX_DIR)/drivers/md/linear.ko
  AUTOLOAD:=$(call AutoLoad,28,linear)
endef

define KernelPackage/md-linear/description
 RAID "Linear" or "Append" driver module (linear.ko)
endef

$(eval $(call KernelPackage,md-linear))


define KernelPackage/md-raid0
$(call KernelPackage/md/Depends,)
  TITLE:=RAID0 Module
  KCONFIG:=CONFIG_MD_RAID0
  FILES:=$(LINUX_DIR)/drivers/md/raid0.ko
  AUTOLOAD:=$(call AutoLoad,28,raid0)
endef

define KernelPackage/md-raid0/description
 RAID Level 0 (Striping) driver module (raid0.ko)
endef

$(eval $(call KernelPackage,md-raid0))


define KernelPackage/md-raid1
$(call KernelPackage/md/Depends,)
  TITLE:=RAID1 Module
  KCONFIG:=CONFIG_MD_RAID1
  FILES:=$(LINUX_DIR)/drivers/md/raid1.ko
  AUTOLOAD:=$(call AutoLoad,28,raid1)
endef

define KernelPackage/md-raid1/description
 RAID Level 1 (Mirroring) driver (raid1.ko)
endef

$(eval $(call KernelPackage,md-raid1))


define KernelPackage/md-raid10
$(call KernelPackage/md/Depends,)
  TITLE:=RAID10 Module
  KCONFIG:=CONFIG_MD_RAID10
  FILES:=$(LINUX_DIR)/drivers/md/raid10.ko
  AUTOLOAD:=$(call AutoLoad,28,raid10)
endef

define KernelPackage/md-raid10/description
 RAID Level 10 (Mirroring+Striping) driver module (raid10.ko)
endef

$(eval $(call KernelPackage,md-raid10))


define KernelPackage/md-raid456
$(call KernelPackage/md/Depends,+kmod-lib-raid6 +kmod-lib-xor +!LINUX_3_18:kmod-lib-crc32c)
  TITLE:=RAID Level 456 Driver
  KCONFIG:= \
       CONFIG_ASYNC_CORE \
       CONFIG_ASYNC_MEMCPY \
       CONFIG_ASYNC_XOR \
       CONFIG_ASYNC_PQ \
       CONFIG_ASYNC_RAID6_RECOV \
       CONFIG_ASYNC_RAID6_TEST=n \
       CONFIG_MD_RAID456 \
       CONFIG_MULTICORE_RAID456=n
  FILES:= \
	$(LINUX_DIR)/crypto/async_tx/async_tx.ko \
	$(LINUX_DIR)/crypto/async_tx/async_memcpy.ko \
	$(LINUX_DIR)/crypto/async_tx/async_xor.ko \
	$(LINUX_DIR)/crypto/async_tx/async_pq.ko \
	$(LINUX_DIR)/crypto/async_tx/async_raid6_recov.ko \
	$(LINUX_DIR)/drivers/md/raid456.ko
  AUTOLOAD:=$(call AutoLoad,28, async_tx async_memcpy async_xor async_pq async_raid6_recov raid456)
endef

define KernelPackage/md-raid456/description
 RAID Level 4,5,6 kernel module (raid456.ko)

 Includes the following modules required by
 raid456.ko:
    xor.ko
    async_tx.ko
    async_xor.ko
    async_memcpy.ko
    async_pq.ko
    async_raid5_recov.ko
    raid6_pq.ko
endef

$(eval $(call KernelPackage,md-raid456))


define KernelPackage/md-multipath
$(call KernelPackage/md/Depends,)
  TITLE:=MD Multipath Module
  KCONFIG:=CONFIG_MD_MULTIPATH
  FILES:=$(LINUX_DIR)/drivers/md/multipath.ko
  AUTOLOAD:=$(call AutoLoad,29,multipath)
endef

define KernelPackage/md-multipath/description
 Multipath driver module (multipath.ko)
endef

$(eval $(call KernelPackage,md-multipath))


define KernelPackage/libsas
  SUBMENU:=$(BLOCK_MENU)
  DEPENDS:=@TARGET_x86
  TITLE:=SAS Domain Transport Attributes
  KCONFIG:=CONFIG_SCSI_SAS_LIBSAS \
	CONFIG_SCSI_SAS_ATTRS \
	CONFIG_SCSI_SAS_ATA=y \
	CONFIG_SCSI_SAS_HOST_SMP=y \
	CONFIG_SCSI_SAS_LIBSAS_DEBUG=y
  FILES:= \
	$(LINUX_DIR)/drivers/scsi/scsi_transport_sas.ko \
	$(LINUX_DIR)/drivers/scsi/libsas/libsas.ko
  AUTOLOAD:=$(call AutoLoad,29,scsi_transport_sas libsas,1)
endef

define KernelPackage/libsas/description
 SAS Domain Transport Attributes support
endef

$(eval $(call KernelPackage,libsas,1))


define KernelPackage/loop
  SUBMENU:=$(BLOCK_MENU)
  TITLE:=Loopback device support
  KCONFIG:= \
	CONFIG_BLK_DEV_LOOP \
	CONFIG_BLK_DEV_CRYPTOLOOP=n
  FILES:=$(LINUX_DIR)/drivers/block/loop.ko
  AUTOLOAD:=$(call AutoLoad,30,loop)
endef

define KernelPackage/loop/description
 Kernel module for loopback device support
endef

$(eval $(call KernelPackage,loop))


define KernelPackage/mvsas
  SUBMENU:=$(BLOCK_MENU)
  TITLE:=Marvell 88SE6440 SAS/SATA driver
  DEPENDS:=@TARGET_x86 +kmod-libsas
  KCONFIG:= \
	CONFIG_SCSI_MVSAS \
	CONFIG_SCSI_MVSAS_TASKLET=n
  FILES:=$(LINUX_DIR)/drivers/scsi/mvsas/mvsas.ko
  AUTOLOAD:=$(call AutoLoad,40,mvsas,1)
endef

define KernelPackage/mvsas/description
 Kernel support for the Marvell SAS SCSI adapters
endef

$(eval $(call KernelPackage,mvsas))


define KernelPackage/nbd
  SUBMENU:=$(BLOCK_MENU)
  TITLE:=Network block device support
  KCONFIG:=CONFIG_BLK_DEV_NBD
  FILES:=$(LINUX_DIR)/drivers/block/nbd.ko
  AUTOLOAD:=$(call AutoLoad,30,nbd)
endef

define KernelPackage/nbd/description
 Kernel module for network block device support
endef

$(eval $(call KernelPackage,nbd))


define KernelPackage/scsi-core
  SUBMENU:=$(BLOCK_MENU)
  TITLE:=SCSI device support
  KCONFIG:= \
	CONFIG_SCSI \
	CONFIG_BLK_DEV_SD
  FILES:= \
	$(LINUX_DIR)/drivers/scsi/scsi_mod.ko \
	$(LINUX_DIR)/drivers/scsi/sd_mod.ko
  AUTOLOAD:=$(call AutoLoad,40,scsi_mod sd_mod,1)
endef

$(eval $(call KernelPackage,scsi-core))


define KernelPackage/scsi-generic
  SUBMENU:=$(BLOCK_MENU)
  TITLE:=Kernel support for SCSI generic
  DEPENDS:=+kmod-scsi-core
  KCONFIG:= \
	CONFIG_CHR_DEV_SG
  FILES:= \
	$(LINUX_DIR)/drivers/scsi/sg.ko
  AUTOLOAD:=$(call AutoLoad,65,sg)
endef

$(eval $(call KernelPackage,scsi-generic))


define KernelPackage/scsi-cdrom
  SUBMENU:=$(BLOCK_MENU)
  TITLE:=Kernel support for CD / DVD drives
  DEPENDS:=+kmod-scsi-core
  KCONFIG:= \
    CONFIG_BLK_DEV_SR \
    CONFIG_BLK_DEV_SR_VENDOR=n
  FILES:= \
    $(LINUX_DIR)/drivers/cdrom/cdrom.ko \
    $(LINUX_DIR)/drivers/scsi/sr_mod.ko
  AUTOLOAD:=$(call AutoLoad,45,sr_mod)
endef

$(eval $(call KernelPackage,scsi-cdrom))


define KernelPackage/scsi-tape
  SUBMENU:=$(BLOCK_MENU)
  TITLE:=Kernel support for scsi tape drives
  DEPENDS:=+kmod-scsi-core
  KCONFIG:= \
    CONFIG_CHR_DEV_ST
  FILES:= \
    $(LINUX_DIR)/drivers/scsi/st.ko
  AUTOLOAD:=$(call AutoLoad,45,st)
endef

$(eval $(call KernelPackage,scsi-tape))