# HG changeset patch # User Louis Opter # Date 1326034338 -3600 # Node ID 0ff39df29c46939a724b9e98b348b9e133fdbdb1 # Parent d761c8c625d39f724bcca2ad797e99a8b269b350 Add the code to reset the card diff -r d761c8c625d3 -r 0ff39df29c46 rathaxes_add_lkm_ethernet_sample.patch --- a/rathaxes_add_lkm_ethernet_sample.patch Sun Jan 08 14:47:03 2012 +0100 +++ b/rathaxes_add_lkm_ethernet_sample.patch Sun Jan 08 15:52:18 2012 +0100 @@ -2,6 +2,18 @@ # Parent b995d8934956b83383c144303178f3eb383d0acf rathaxes: add the PCI/Ethernet part of a Linux Intel e1000 network card driver +diff --git a/maintainers/CMakeScripts/UseRathaxes.cmake b/maintainers/CMakeScripts/UseRathaxes.cmake +--- a/maintainers/CMakeScripts/UseRathaxes.cmake ++++ b/maintainers/CMakeScripts/UseRathaxes.cmake +@@ -193,6 +193,8 @@ + + SET(KERNEL_OBJECT_NAME "${RATHAXES_SOURCE}_${SYSTEM}.ko") + ADD_CUSTOM_COMMAND(OUTPUT "${KERNEL_OBJECT_NAME}" ++ # … ++ COMMAND "sed" "-i" "/TARTE/ d" "${RATHAXES_SOURCE}_${SYSTEM}.c" + # The linux Makefile to build kernel module is quite + # picky about file location and its own name. Let's + # copy our source side by side with the Makefile: diff --git a/rathaxes/samples/CMakeLists.txt b/rathaxes/samples/CMakeLists.txt --- a/rathaxes/samples/CMakeLists.txt +++ b/rathaxes/samples/CMakeLists.txt @@ -25,7 +37,7 @@ new file mode 100644 --- /dev/null +++ b/rathaxes/samples/lkm/e1000.blt -@@ -0,0 +1,170 @@ +@@ -0,0 +1,267 @@ +with e1000, Ethernet, Socket, PCI, LKM, Log +{ + template type e1000::Context() @@ -73,14 +85,14 @@ + { + enum rtx_e1000_registers + { -+ E1000_CTRL = 0x00000, -+ E1000_CTRL_DUP = 0x00004, -+ E1000_STATUS = 0x00008, -+ E1000_EEPROM_FLASH = 0x00010, -+ E1000_EEPROM_READ = 0x00014, -+ E1000_CTRL_EXT = 0x00018, -+ E1000_FLA = 0x0001C, -+ E1000_MDIC = 0x00020, ++ E1000_CTRL = 0x00000, /* Device Control - RW */ ++ E1000_CTRL_DUP = 0x00004, /* Device Control Duplicate (Shadow) - RW */ ++ E1000_STATUS = 0x00008, /* Device Status - RO */ ++ E1000_EEPROM_FLASH = 0x00010, /* EEPROM/Flash Control - RW */ ++ E1000_EEPROM_READ = 0x00014, /* EEPROM Read - RW */ ++ E1000_CTRL_EXT = 0x00018, /* Extended Device Control - RW */ ++ E1000_FLA = 0x0001C, /* Flash Access - RW */ ++ E1000_MDIC = 0x00020 /* MDI Control - RW */ + }; + } + @@ -94,6 +106,62 @@ + } + } + ++ template type e1000::Commands() ++ { ++ chunk LKM::includes() ++ { ++ typedef int ${e1000::Commands}; ++ static const ${e1000::Commands} force_enum_rtx_e1000_commands_decls; ++ } ++ ++ chunk ::decl() ++ { ++ enum rtx_e1000_commands ++ { ++ E1000_CMD_FD = 0x00000001, /* Full duplex.0=half; 1=full */ ++ E1000_CMD_BEM = 0x00000002, /* Endian Mode.0=little,1=big */ ++ E1000_CMD_PRIOR = 0x00000004, /* Priority on PCI. 0=rx,1=fair */ ++ E1000_CMD_GIO_MASTER_DISABLE = 0x00000004, /* Blocks new Master requests */ ++ E1000_CMD_LRST = 0x00000008, /* Link reset. 0=normal,1=reset */ ++ E1000_CMD_TME = 0x00000010, /* Test mode. 0=normal,1=test */ ++ E1000_CMD_SLE = 0x00000020, /* Serial Link on 0=dis,1=en */ ++ E1000_CMD_ASDE = 0x00000020, /* Auto-speed detect enable */ ++ E1000_CMD_SLU = 0x00000040, /* Set link up (Force Link) */ ++ E1000_CMD_ILOS = 0x00000080, /* Invert Loss-Of Signal */ ++ E1000_CMD_SPD_SEL = 0x00000300, /* Speed Select Mask */ ++ E1000_CMD_SPD_10 = 0x00000000, /* Force 10Mb */ ++ E1000_CMD_SPD_100 = 0x00000100, /* Force 100Mb */ ++ E1000_CMD_SPD_1000 = 0x00000200, /* Force 1Gb */ ++ E1000_CMD_BEM32 = 0x00000400, /* Big Endian 32 mode */ ++ E1000_CMD_FRCSPD = 0x00000800, /* Force Speed */ ++ E1000_CMD_FRCDPX = 0x00001000, /* Force Duplex */ ++ E1000_CMD_D_UD_EN = 0x00002000, /* Dock/Undock enable */ ++ E1000_CMD_D_UD_POLARITY = 0x00004000, /* Defined polarity of Dock/Undock indication in SDP[0] */ ++ E1000_CMD_FORCE_PHY_RESET = 0x00008000, /* Reset both PHY ports, through PHYRST_N pin */ ++ E1000_CMD_EXT_LINK_EN = 0x00010000, /* enable link status from external LINK_0 and LINK_1 pins */ ++ E1000_CMD_SWDPIN0 = 0x00040000, /* SWDPIN 0 value */ ++ E1000_CMD_SWDPIN1 = 0x00080000, /* SWDPIN 1 value */ ++ E1000_CMD_SWDPIN2 = 0x00100000, /* SWDPIN 2 value */ ++ E1000_CMD_SWDPIN3 = 0x00200000, /* SWDPIN 3 value */ ++ E1000_CMD_SWDPIO0 = 0x00400000, /* SWDPIN 0 Input or output */ ++ E1000_CMD_SWDPIO1 = 0x00800000, /* SWDPIN 1 input or output */ ++ E1000_CMD_SWDPIO2 = 0x01000000, /* SWDPIN 2 input or output */ ++ E1000_CMD_SWDPIO3 = 0x02000000, /* SWDPIN 3 input or output */ ++ E1000_CMD_RST = 0x04000000, /* Global reset */ ++ E1000_CMD_RFCE = 0x08000000, /* Receive Flow Control enable */ ++ E1000_CMD_TFCE = 0x10000000, /* Transmit flow control enable */ ++ E1000_CMD_RTE = 0x20000000, /* Routing tag enable */ ++ E1000_CMD_VME = 0x40000000, /* IEEE VLAN mode enable */ ++ E1000_CMD_PHY_RST = 0x80000000, /* PHY Reset */ ++ E1000_CMD_SW2FW_INT = 0x02000000 /* Initiate an interrupt to manageability engine */ ++ }; ++ } ++ ++ map ++ { ++ } ++ } ++ + template sequence e1000::create_device() + { + chunk Ethernet::create_device() @@ -121,35 +189,12 @@ + ${Log::info("e1000::create: pci_ioremap_bar failed")}; + } + -+ /* Now we can reset the card and load its mac address */ ++ rtx_e1000_print_status(&rtx_ether_ctx->hw_ctx); ++ /* Reset the card */ ++ rtx_e1000_register_write32(&rtx_ether_ctx->hw_ctx, E1000_CTRL, E1000_CMD_RST); ++ rtx_e1000_print_status(&rtx_ether_ctx->hw_ctx); + -+ /* -+ * We should have been able to do something along those lines, but -+ * it didn't work so we made the call manually. -+ * -+ * Ideally: -+ * ${e1000::register_read32(rtx_ether_ctx->hw_ctx, E1000_STATUS)}; -+ * -+ * Ideally2, not sure about the syntax on the register parameter: -+ * ${e1000::register_read32(rtx_ether_ctx->hw_ctx, ${e1000::Register.E1000_STATUS})}; -+ * -+ * "Acceptable": -+ * typedef int ${e1000::Register}; // cnorm __std__ workaround -+ * ${e1000::Register} reg_status; -+ * ${e1000.init(E1000_STATUS); // didn't work, so we used the next line -+ * reg_status = E1000_STATUS; -+ * ${e1000::register_read32(rtx_ether_ctx->hw_ctx, reg_status)}; -+ * -+ */ -+ -+ unsigned int status = rtx_e1000_register_read32(&rtx_ether_ctx->hw_ctx, E1000_STATUS); -+ -+ pr_info("Status of the e1000 card:\n"); -+ pr_info("\tStatus: %i\n", status); -+ pr_info("\tMode: %s\n", (status & 1) ? "Full": "Half"); -+ pr_info("\tLink: %s\n", (status & 2) ? "UP" : "Down"); -+ pr_info("\tTransmission: %s\n", (status & 4) ? "Paused" : "Ok"); -+ pr_info("\tInterface: %s\n", (status & 3) == 3 ? "UP" : "Down"); ++ /* Now we can load its mac address */ + } + + chunk ::CALL @@ -175,6 +220,49 @@ + } + } + ++ template sequence e1000::print_status() ++ { ++ chunk LKM::prototypes() ++ { ++ static void rtx_e1000_print_status(struct rtx_e1000_ctx *); ++ } ++ ++ chunk LKM::code() ++ { ++ static void rtx_e1000_print_status(struct rtx_e1000_ctx *ctx) ++ { ++ unsigned int status = rtx_e1000_register_read32(ctx, E1000_STATUS); ++ pr_info("rtx_e1000 status: \n"); ++ pr_info("\tRegister value: 0x%x\n", status); ++ pr_info("\tMode: %s\n", (status & 1) ? "Full": "Half"); ++ pr_info("\tLink: %s\n", (status & 2) ? "Up" : "Down"); ++ pr_info("\tTransmission: %s\n", (status & 4) ? "Paused" : "Ok"); ++ pr_info("\tInterface: %s\n", (status & 3) == 3 ? "Up" : "Down"); ++ } ++ } ++ ++ chunk ::CALL ++ { ++ } ++ } ++ ++ /* ++ * We should have been able to do something along those lines, but ++ * it didn't work so we made the call manually. ++ * ++ * Ideally: ++ * ${e1000::register_read32(rtx_ether_ctx->hw_ctx, E1000_STATUS)}; ++ * ++ * Ideally2, not sure about the syntax on the register parameter: ++ * ${e1000::register_read32(rtx_ether_ctx->hw_ctx, ${e1000::Register.E1000_STATUS})}; ++ * ++ * "Acceptable": ++ * typedef int ${e1000::Register}; // cnorm __std__ workaround ++ * ${e1000::Register} reg_status; ++ * ${e1000.init(E1000_STATUS); // didn't work, so we used the next line ++ * reg_status = E1000_STATUS; ++ * ${e1000::register_read32(rtx_ether_ctx->hw_ctx, reg_status)}; ++ */ + template sequence e1000::register_read32(e1000::Context ctx, e1000::Register reg_offset) + { + chunk LKM::prototypes() @@ -195,16 +283,38 @@ + rtx_e1000_register_read32(&${ctx}, ${reg_offset}); + } + } ++ ++ template sequence e1000::register_write32(e1000::Context ctx, e1000::Register reg_offset, ::number value) ++ { ++ chunk LKM::prototypes() ++ { ++ static void rtx_e1000_register_write32(struct rtx_e1000_ctx *, unsigned int, unsigned int); ++ } ++ ++ chunk LKM::code() ++ { ++ static void rtx_e1000_register_write32(struct rtx_e1000_ctx *ctx, unsigned int reg_offset, unsigned int value) ++ { ++ iowrite32(value, ctx->ioaddr + reg_offset); ++ } ++ } ++ ++ chunk ::CALL() ++ { ++ rtx_e1000_register_write32(&${ctx}, ${reg_offset}); ++ } ++ } +} diff --git a/rathaxes/samples/lkm/e1000.rti b/rathaxes/samples/lkm/e1000.rti new file mode 100644 --- /dev/null +++ b/rathaxes/samples/lkm/e1000.rti -@@ -0,0 +1,39 @@ +@@ -0,0 +1,51 @@ +interface e1000 : Socket, Ethernet, PCI, LKM +{ + provided type e1000::Context; + provided type e1000::Register; ++ provided type e1000::Commands; + + /* + * This sequence should receive an argument like Ethernet::Device, but it is @@ -227,18 +337,29 @@ + } + + /* -+ * It should also take an e1000::Context argument as the first parameter. -+ * But we weren't able to call the sequence afterwards, with expression -+ * like: -+ * -+ * ${e1000::register_read32(rtx_ether_ctx->hw_ctx, E1000_STATUS)}; ++ * This should take an e1000::Context as the first argument but this was ++ * not working as wished. + */ ++ provided sequence e1000::print_status() ++ { ++ provided chunk LKM::prototypes; ++ provided chunk LKM::code; ++ provided chunk ::CALL; ++ } ++ + provided sequence e1000::register_read32(e1000::Context, e1000::Register) + { + provided chunk LKM::prototypes; + provided chunk LKM::code; + provided chunk ::CALL; + } ++ ++ provided sequence e1000::register_write32(e1000::Context, e1000::Register, ::number) ++ { ++ provided chunk LKM::prototypes; ++ provided chunk LKM::code; ++ provided chunk ::CALL; ++ } +} diff --git a/rathaxes/samples/lkm/ethernet.blt b/rathaxes/samples/lkm/ethernet.blt new file mode 100644