From owner-svn-src-user@FreeBSD.ORG Thu Oct 9 01:34:28 2008 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A3A42106568E; Thu, 9 Oct 2008 01:34:28 +0000 (UTC) (envelope-from peter@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 8F08C8FC18; Thu, 9 Oct 2008 01:34:28 +0000 (UTC) (envelope-from peter@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m991YSO4048231; Thu, 9 Oct 2008 01:34:28 GMT (envelope-from peter@svn.freebsd.org) Received: (from peter@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m991YSaQ048219; Thu, 9 Oct 2008 01:34:28 GMT (envelope-from peter@svn.freebsd.org) Message-Id: <200810090134.m991YSaQ048219@svn.freebsd.org> From: Peter Wemm Date: Thu, 9 Oct 2008 01:34:28 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r183713 - in user/peter/long_cpumask/sys: . dev/e1000 dev/iicbus dev/mmc dev/pcn dev/sio dev/sis dev/ste dev/tl dev/usb dev/wb dev/xl kern mips/adm5120 mips/idt mips/malta mips/sentry5 ... X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 09 Oct 2008 01:34:28 -0000 Author: peter Date: Thu Oct 9 01:34:27 2008 New Revision: 183713 URL: http://svn.freebsd.org/changeset/base/183713 Log: Merge r183687 through r183712 into wip branch. Suffer mergeinfo whiplash. Modified: user/peter/long_cpumask/sys/ (props changed) user/peter/long_cpumask/sys/dev/e1000/ (props changed) user/peter/long_cpumask/sys/dev/e1000/e1000_82575.c (props changed) user/peter/long_cpumask/sys/dev/e1000/e1000_82575.h (props changed) user/peter/long_cpumask/sys/dev/e1000/if_igb.c (props changed) user/peter/long_cpumask/sys/dev/e1000/if_igb.h (props changed) user/peter/long_cpumask/sys/dev/iicbus/ds133x.c (props changed) user/peter/long_cpumask/sys/dev/mmc/bridge.h user/peter/long_cpumask/sys/dev/mmc/mmc.c user/peter/long_cpumask/sys/dev/mmc/mmcbrvar.h user/peter/long_cpumask/sys/dev/mmc/mmcreg.h user/peter/long_cpumask/sys/dev/mmc/mmcsd.c user/peter/long_cpumask/sys/dev/mmc/mmcvar.h user/peter/long_cpumask/sys/dev/pcn/if_pcn.c (props changed) user/peter/long_cpumask/sys/dev/pcn/if_pcnreg.h (props changed) user/peter/long_cpumask/sys/dev/sio/sio.c user/peter/long_cpumask/sys/dev/sis/if_sis.c (props changed) user/peter/long_cpumask/sys/dev/sis/if_sisreg.h (props changed) user/peter/long_cpumask/sys/dev/ste/if_ste.c (props changed) user/peter/long_cpumask/sys/dev/ste/if_stereg.h (props changed) user/peter/long_cpumask/sys/dev/tl/if_tl.c (props changed) user/peter/long_cpumask/sys/dev/tl/if_tlreg.h (props changed) user/peter/long_cpumask/sys/dev/usb/umass.c user/peter/long_cpumask/sys/dev/usb/usbdevs user/peter/long_cpumask/sys/dev/wb/if_wb.c (props changed) user/peter/long_cpumask/sys/dev/wb/if_wbreg.h (props changed) user/peter/long_cpumask/sys/dev/xl/if_xl.c (props changed) user/peter/long_cpumask/sys/dev/xl/if_xlreg.h (props changed) user/peter/long_cpumask/sys/kern/imgact_elf.c user/peter/long_cpumask/sys/kern/uipc_usrreq.c user/peter/long_cpumask/sys/mips/adm5120/ (props changed) user/peter/long_cpumask/sys/mips/idt/ (props changed) user/peter/long_cpumask/sys/mips/malta/ (props changed) user/peter/long_cpumask/sys/mips/sentry5/ (props changed) user/peter/long_cpumask/sys/netgraph/netflow/netflow.c user/peter/long_cpumask/sys/netgraph/netflow/ng_netflow.c user/peter/long_cpumask/sys/netgraph/netflow/ng_netflow.h Modified: user/peter/long_cpumask/sys/dev/mmc/bridge.h ============================================================================== --- user/peter/long_cpumask/sys/dev/mmc/bridge.h Wed Oct 8 21:46:17 2008 (r183712) +++ user/peter/long_cpumask/sys/dev/mmc/bridge.h Thu Oct 9 01:34:27 2008 (r183713) @@ -104,6 +104,10 @@ enum mmc_bus_width { bus_width_1 = 0, bus_width_4 = 2, bus_width_8 = 3 }; +enum mmc_bus_timing { + bus_timing_normal = 0, bus_timing_hs +}; + struct mmc_ios { uint32_t clock; /* Speed of the clock in Hz to move data */ enum mmc_vdd vdd; /* Voltage to apply to the power pins/ */ @@ -111,6 +115,7 @@ struct mmc_ios { enum mmc_chip_select chip_select; enum mmc_bus_width bus_width; enum mmc_power_mode power_mode; + enum mmc_bus_timing timing; }; enum mmc_card_mode { @@ -125,6 +130,7 @@ struct mmc_host { uint32_t caps; #define MMC_CAP_4_BIT_DATA (1 << 0) /* Can do 4-bit data transfers */ #define MMC_CAP_8_BIT_DATA (1 << 1) /* Can do 8-bit data transfers */ +#define MMC_CAP_HSPEED (1 << 2) /* Can do High Speed transfers */ enum mmc_card_mode mode; struct mmc_ios ios; /* Current state of the host */ }; Modified: user/peter/long_cpumask/sys/dev/mmc/mmc.c ============================================================================== --- user/peter/long_cpumask/sys/dev/mmc/mmc.c Wed Oct 8 21:46:17 2008 (r183712) +++ user/peter/long_cpumask/sys/dev/mmc/mmc.c Thu Oct 9 01:34:27 2008 (r183713) @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -82,11 +83,19 @@ struct mmc_softc { struct mmc_ivars { uint32_t raw_cid[4]; /* Raw bits of the CID */ uint32_t raw_csd[4]; /* Raw bits of the CSD */ + uint32_t raw_scr[2]; /* Raw bits of the SCR */ + uint8_t raw_ext_csd[512]; /* Raw bits of the EXT_CSD */ uint16_t rca; enum mmc_card_mode mode; struct mmc_cid cid; /* cid decoded */ struct mmc_csd csd; /* csd decoded */ + struct mmc_scr scr; /* scr decoded */ u_char read_only; /* True when the device is read-only */ + u_char bus_width; /* Bus width to use */ + u_char timing; /* Bus timing support */ + u_char high_cap; /* High Capacity card */ + uint32_t tran_speed; /* Max speed in normal mode */ + uint32_t hs_tran_speed; /* Max speed in high speed mode */ }; #define CMD_RETRIES 3 @@ -111,6 +120,11 @@ static int mmc_wait_for_cmd(struct mmc_s int retries); static int mmc_wait_for_command(struct mmc_softc *sc, uint32_t opcode, uint32_t arg, uint32_t flags, uint32_t *resp, int retries); +static int mmc_select_card(struct mmc_softc *sc, uint16_t rca); +static int mmc_set_bus_width(struct mmc_softc *sc, uint16_t rca, int width); +static int mmc_app_send_scr(struct mmc_softc *sc, uint16_t rca, uint32_t *rawscr); +static void mmc_app_decode_scr(uint32_t *raw_scr, struct mmc_scr *scr); +static int mmc_send_ext_csd(struct mmc_softc *sc, uint8_t *rawextcsd); static void mmc_ms_delay(int ms) @@ -173,6 +187,7 @@ static int mmc_acquire_bus(device_t busdev, device_t dev) { struct mmc_softc *sc; + struct mmc_ivars *ivar; int err; int rca; @@ -195,21 +210,26 @@ mmc_acquire_bus(device_t busdev, device_ */ rca = mmc_get_rca(dev); if (sc->last_rca != rca) { - mmc_wait_for_command(sc, MMC_SELECT_CARD, rca << 16, - MMC_RSP_R1 | MMC_CMD_AC, NULL, CMD_RETRIES); + mmc_select_card(sc, rca); sc->last_rca = rca; + /* Prepare bus width for the new card. */ + ivar = device_get_ivars(dev); + device_printf(busdev, + "setting bus width to %d bits\n", + (ivar->bus_width == bus_width_4)?4: + (ivar->bus_width == bus_width_8)?8:1); + mmc_set_bus_width(sc, rca, ivar->bus_width); + mmcbr_set_bus_width(busdev, ivar->bus_width); + mmcbr_update_ios(busdev); } - /* XXX should set bus width here? */ } else { /* * If there's a card selected, stand down. */ if (sc->last_rca != 0) { - mmc_wait_for_command(sc, MMC_SELECT_CARD, 0, - MMC_RSP_R1 | MMC_CMD_AC, NULL, CMD_RETRIES); + mmc_select_card(sc, 0); sc->last_rca = 0; } - /* XXX should set bus width here? */ } return (0); @@ -408,7 +428,8 @@ mmc_send_app_op_cond(struct mmc_softc *s err = mmc_wait_for_app_cmd(sc, 0, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) break; - if ((cmd.resp[0] & MMC_OCR_CARD_BUSY) || ocr == 0) + if ((cmd.resp[0] & MMC_OCR_CARD_BUSY) || + (ocr & MMC_OCR_VOLTAGE) == 0) break; err = MMC_ERR_TIMEOUT; mmc_ms_delay(10); @@ -434,7 +455,8 @@ mmc_send_op_cond(struct mmc_softc *sc, u err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) break; - if ((cmd.resp[0] & MMC_OCR_CARD_BUSY) || ocr == 0) + if ((cmd.resp[0] & MMC_OCR_CARD_BUSY) || + (ocr & MMC_OCR_VOLTAGE) == 0) break; err = MMC_ERR_TIMEOUT; mmc_ms_delay(10); @@ -444,6 +466,22 @@ mmc_send_op_cond(struct mmc_softc *sc, u return (err); } +static int +mmc_send_if_cond(struct mmc_softc *sc, uint8_t vhs) +{ + struct mmc_command cmd; + int err; + + memset(&cmd, 0, sizeof(cmd)); + cmd.opcode = SD_SEND_IF_COND; + cmd.arg = (vhs << 8) + 0xAA; + cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR; + cmd.data = NULL; + + err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); + return (err); +} + static void mmc_power_up(struct mmc_softc *sc) { @@ -460,6 +498,7 @@ mmc_power_up(struct mmc_softc *sc) mmc_ms_delay(1); mmcbr_set_clock(dev, mmcbr_get_f_min(sc->dev)); + mmcbr_set_timing(dev, bus_timing_normal); mmcbr_set_power_mode(dev, power_on); mmcbr_update_ios(dev); mmc_ms_delay(2); @@ -475,9 +514,207 @@ mmc_power_down(struct mmc_softc *sc) mmcbr_set_bus_width(dev, bus_width_1); mmcbr_set_power_mode(dev, power_off); mmcbr_set_clock(dev, 0); + mmcbr_set_timing(dev, bus_timing_normal); mmcbr_update_ios(dev); } +static int +mmc_select_card(struct mmc_softc *sc, uint16_t rca) +{ + return (mmc_wait_for_command(sc, MMC_SELECT_CARD, ((uint32_t)rca) << 16, + MMC_RSP_R1B | MMC_CMD_AC, NULL, CMD_RETRIES)); +} + +static int +mmc_switch(struct mmc_softc *sc, uint8_t set, uint8_t index, uint8_t value) +{ + struct mmc_command cmd; + int err; + + cmd.opcode = MMC_SWITCH_FUNC; + cmd.arg = (MMC_SWITCH_FUNC_WR << 24) | + (index << 16) | + (value << 8) | + set; + cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; + cmd.data = NULL; + err = mmc_wait_for_cmd(sc, &cmd, 0); + return (err); +} + +static int +mmc_sd_switch(struct mmc_softc *sc, uint8_t mode, uint8_t grp, uint8_t value, uint8_t *res) +{ + int err; + struct mmc_command cmd; + struct mmc_data data; + + memset(&cmd, 0, sizeof(struct mmc_command)); + memset(&data, 0, sizeof(struct mmc_data)); + + memset(res, 0, 64); + cmd.opcode = SD_SWITCH_FUNC; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + cmd.arg = mode << 31; + cmd.arg |= 0x00FFFFFF; + cmd.arg &= ~(0xF << (grp * 4)); + cmd.arg |= value << (grp * 4); + cmd.data = &data; + + data.data = res; + data.len = 64; + data.flags = MMC_DATA_READ; + + err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); + return (err); +} + +static int +mmc_set_bus_width(struct mmc_softc *sc, uint16_t rca, int width) +{ + int err; + + if (mmcbr_get_mode(sc->dev) == mode_sd) { + struct mmc_command cmd; + + memset(&cmd, 0, sizeof(struct mmc_command)); + cmd.opcode = ACMD_SET_BUS_WIDTH; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; + switch (width) { + case bus_width_1: + cmd.arg = SD_BUS_WIDTH_1; + break; + case bus_width_4: + cmd.arg = SD_BUS_WIDTH_4; + break; + default: + return (MMC_ERR_INVALID); + } + err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES); + } else { + uint8_t value; + + switch (width) { + case bus_width_1: + value = EXT_CSD_BUS_WIDTH_1; + break; + case bus_width_4: + value = EXT_CSD_BUS_WIDTH_4; + break; + case bus_width_8: + value = EXT_CSD_BUS_WIDTH_8; + break; + default: + return (MMC_ERR_INVALID); + } + err = mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, value); + } + return (err); +} + +static int +mmc_set_timing(struct mmc_softc *sc, int timing) +{ + int err; + uint8_t value; + + switch (timing) { + case bus_timing_normal: + value = 0; + break; + case bus_timing_hs: + value = 1; + break; + default: + return (MMC_ERR_INVALID); + } + if (mmcbr_get_mode(sc->dev) == mode_sd) { + u_char switch_res[64]; + + err = mmc_sd_switch(sc, 1, 0, value, switch_res); + } else { + err = mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_HS_TIMING, value); + } + return (err); +} + +static int +mmc_test_bus_width(struct mmc_softc *sc) +{ + struct mmc_command cmd; + struct mmc_data data; + int err; + uint8_t buf[8]; + uint8_t p8[8] = { 0x55, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t p8ok[8] = { 0xAA, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t p4[4] = { 0x5A, 0x00, 0x00, 0x00, }; + uint8_t p4ok[4] = { 0xA5, 0x00, 0x00, 0x00, }; + + if (mmcbr_get_caps(sc->dev) & MMC_CAP_8_BIT_DATA) { + mmcbr_set_bus_width(sc->dev, bus_width_8); + mmcbr_update_ios(sc->dev); + + cmd.opcode = MMC_BUSTEST_W; + cmd.arg = 0; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + cmd.data = &data; + + data.data = p8; + data.len = 8; + data.flags = MMC_DATA_WRITE; + mmc_wait_for_cmd(sc, &cmd, 0); + + cmd.opcode = MMC_BUSTEST_R; + cmd.arg = 0; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + cmd.data = &data; + + data.data = buf; + data.len = 8; + data.flags = MMC_DATA_READ; + err = mmc_wait_for_cmd(sc, &cmd, 0); + + mmcbr_set_bus_width(sc->dev, bus_width_1); + mmcbr_update_ios(sc->dev); + + if (err == MMC_ERR_NONE && memcmp(buf, p8ok, 8) == 0) + return (bus_width_8); + } + + if (mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) { + mmcbr_set_bus_width(sc->dev, bus_width_4); + mmcbr_update_ios(sc->dev); + + cmd.opcode = MMC_BUSTEST_W; + cmd.arg = 0; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + cmd.data = &data; + + data.data = p4; + data.len = 4; + data.flags = MMC_DATA_WRITE; + mmc_wait_for_cmd(sc, &cmd, 0); + + cmd.opcode = MMC_BUSTEST_R; + cmd.arg = 0; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + cmd.data = &data; + + data.data = buf; + data.len = 4; + data.flags = MMC_DATA_READ; + err = mmc_wait_for_cmd(sc, &cmd, 0); + + mmcbr_set_bus_width(sc->dev, bus_width_1); + mmcbr_update_ios(sc->dev); + + if (err == MMC_ERR_NONE && memcmp(buf, p4ok, 4) == 0) + return (bus_width_4); + } + return (bus_width_1); +} + static uint32_t mmc_get_bits(uint32_t *bits, int start, int size) { @@ -506,8 +743,14 @@ mmc_decode_cid(int is_sd, uint32_t *raw_ cid->mdt_year = mmc_get_bits(raw_cid, 12, 8) + 2001; cid->mdt_month = mmc_get_bits(raw_cid, 8, 4); } else { - /* XXX write me */ - panic("write mmc cid decoder"); + cid->mid = mmc_get_bits(raw_cid, 120, 8); + cid->oid = mmc_get_bits(raw_cid, 104, 8); + for (i = 0; i < 6; i++) + cid->pnm[i] = mmc_get_bits(raw_cid, 96 - i * 8, 8); + cid->prv = mmc_get_bits(raw_cid, 48, 8); + cid->psn = mmc_get_bits(raw_cid, 16, 32); + cid->mdt_month = mmc_get_bits(raw_cid, 12, 4); + cid->mdt_year = mmc_get_bits(raw_cid, 8, 4) + 1997; } } @@ -563,12 +806,82 @@ mmc_decode_csd(int is_sd, uint32_t *raw_ csd->write_bl_len = 1 << mmc_get_bits(raw_csd, 22, 4); csd->write_bl_partial = mmc_get_bits(raw_csd, 21, 1); } else if (v == 1) { - panic("Write SDHC CSD parser"); + m = mmc_get_bits(raw_csd, 115, 4); + e = mmc_get_bits(raw_csd, 112, 3); + csd->tacc = exp[e] * mant[m] + 9 / 10; + csd->nsac = mmc_get_bits(raw_csd, 104, 8) * 100; + m = mmc_get_bits(raw_csd, 99, 4); + e = mmc_get_bits(raw_csd, 96, 3); + csd->tran_speed = exp[e] * 10000 * mant[m]; + csd->ccc = mmc_get_bits(raw_csd, 84, 12); + csd->read_bl_len = 1 << mmc_get_bits(raw_csd, 80, 4); + csd->read_bl_partial = mmc_get_bits(raw_csd, 79, 1); + csd->write_blk_misalign = mmc_get_bits(raw_csd, 78, 1); + csd->read_blk_misalign = mmc_get_bits(raw_csd, 77, 1); + csd->dsr_imp = mmc_get_bits(raw_csd, 76, 1); + csd->capacity = ((uint64_t)mmc_get_bits(raw_csd, 48, 22) + 1) * + 512 * 1024; + csd->erase_blk_en = mmc_get_bits(raw_csd, 46, 1); + csd->sector_size = mmc_get_bits(raw_csd, 39, 7); + csd->wp_grp_size = mmc_get_bits(raw_csd, 32, 7); + csd->wp_grp_enable = mmc_get_bits(raw_csd, 31, 1); + csd->r2w_factor = 1 << mmc_get_bits(raw_csd, 26, 3); + csd->write_bl_len = 1 << mmc_get_bits(raw_csd, 22, 4); + csd->write_bl_partial = mmc_get_bits(raw_csd, 21, 1); } else panic("unknown SD CSD version"); } else { - panic("Write a MMC CSD parser"); + csd->csd_structure = mmc_get_bits(raw_csd, 126, 2); + csd->spec_vers = mmc_get_bits(raw_csd, 122, 4); + m = mmc_get_bits(raw_csd, 115, 4); + e = mmc_get_bits(raw_csd, 112, 3); + csd->tacc = exp[e] * mant[m] + 9 / 10; + csd->nsac = mmc_get_bits(raw_csd, 104, 8) * 100; + m = mmc_get_bits(raw_csd, 99, 4); + e = mmc_get_bits(raw_csd, 96, 3); + csd->tran_speed = exp[e] * 10000 * mant[m]; + csd->ccc = mmc_get_bits(raw_csd, 84, 12); + csd->read_bl_len = 1 << mmc_get_bits(raw_csd, 80, 4); + csd->read_bl_partial = mmc_get_bits(raw_csd, 79, 1); + csd->write_blk_misalign = mmc_get_bits(raw_csd, 78, 1); + csd->read_blk_misalign = mmc_get_bits(raw_csd, 77, 1); + csd->dsr_imp = mmc_get_bits(raw_csd, 76, 1); + csd->vdd_r_curr_min = cur_min[mmc_get_bits(raw_csd, 59, 3)]; + csd->vdd_r_curr_max = cur_max[mmc_get_bits(raw_csd, 56, 3)]; + csd->vdd_w_curr_min = cur_min[mmc_get_bits(raw_csd, 53, 3)]; + csd->vdd_w_curr_max = cur_max[mmc_get_bits(raw_csd, 50, 3)]; + m = mmc_get_bits(raw_csd, 62, 12); + e = mmc_get_bits(raw_csd, 47, 3); + csd->capacity = ((1 + m) << (e + 2)) * csd->read_bl_len; +// csd->erase_blk_en = mmc_get_bits(raw_csd, 46, 1); +// csd->sector_size = mmc_get_bits(raw_csd, 39, 7); + csd->wp_grp_size = mmc_get_bits(raw_csd, 32, 5); + csd->wp_grp_enable = mmc_get_bits(raw_csd, 31, 1); + csd->r2w_factor = 1 << mmc_get_bits(raw_csd, 26, 3); + csd->write_bl_len = 1 << mmc_get_bits(raw_csd, 22, 4); + csd->write_bl_partial = mmc_get_bits(raw_csd, 21, 1); + } +} + +static void +mmc_app_decode_scr(uint32_t *raw_scr, struct mmc_scr *scr) +{ + unsigned int scr_struct; + uint32_t tmp[4]; + + tmp[3] = raw_scr[1]; + tmp[2] = raw_scr[0]; + + memset(scr, 0, sizeof(*scr)); + + scr_struct = mmc_get_bits(tmp, 60, 4); + if (scr_struct != 0) { + printf("Unrecognised SCR structure version %d\n", + scr_struct); + return; } + scr->sda_vsn = mmc_get_bits(tmp, 56, 4); + scr->bus_widths = mmc_get_bits(tmp, 48, 4); } static int @@ -602,6 +915,70 @@ mmc_send_csd(struct mmc_softc *sc, uint1 } static int +mmc_app_send_scr(struct mmc_softc *sc, uint16_t rca, uint32_t *rawscr) +{ + int err; + struct mmc_command cmd; + struct mmc_data data; + + memset(&cmd, 0, sizeof(struct mmc_command)); + memset(&data, 0, sizeof(struct mmc_data)); + + memset(rawscr, 0, 8); + cmd.opcode = ACMD_SEND_SCR; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + cmd.arg = 0; + cmd.data = &data; + + data.data = rawscr; + data.len = 8; + data.flags = MMC_DATA_READ; + + err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES); + rawscr[0] = be32toh(rawscr[0]); + rawscr[1] = be32toh(rawscr[1]); + return (err); +} + +static int +mmc_send_ext_csd(struct mmc_softc *sc, uint8_t *rawextcsd) +{ + int err; + struct mmc_command cmd; + struct mmc_data data; + + memset(&cmd, 0, sizeof(struct mmc_command)); + memset(&data, 0, sizeof(struct mmc_data)); + + memset(rawextcsd, 0, 512); + cmd.opcode = MMC_SEND_EXT_CSD; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + cmd.arg = 0; + cmd.data = &data; + + data.data = rawextcsd; + data.len = 512; + data.flags = MMC_DATA_READ; + + err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); + return (err); +} + +static int +mmc_set_relative_addr(struct mmc_softc *sc, uint16_t resp) +{ + struct mmc_command cmd; + int err; + + cmd.opcode = MMC_SET_RELATIVE_ADDR; + cmd.arg = resp << 16; + cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR; + cmd.data = NULL; + err = mmc_wait_for_cmd(sc, &cmd, 0); + return (err); +} + +static int mmc_send_relative_addr(struct mmc_softc *sc, uint32_t *resp) { struct mmc_command cmd; @@ -623,6 +1000,8 @@ mmc_discover_cards(struct mmc_softc *sc) int err; uint32_t resp; device_t child; + uint16_t rca = 2; + u_char switch_res[64]; while (1) { ivar = malloc(sizeof(struct mmc_ivars), M_DEVBUF, @@ -636,22 +1015,75 @@ mmc_discover_cards(struct mmc_softc *sc) device_printf(sc->dev, "Error reading CID %d\n", err); break; } - if (mmcbr_get_mode(sc->dev) == mode_sd) { - ivar->mode = mode_sd; + if (mmcbr_get_ro(sc->dev)) + ivar->read_only = 1; + ivar->bus_width = bus_width_1; + ivar->mode = mmcbr_get_mode(sc->dev); + if (ivar->mode == mode_sd) { mmc_decode_cid(1, ivar->raw_cid, &ivar->cid); mmc_send_relative_addr(sc, &resp); ivar->rca = resp >> 16; - if (mmcbr_get_ro(sc->dev)) - ivar->read_only = 1; + /* Get card CSD. */ mmc_send_csd(sc, ivar->rca, ivar->raw_csd); mmc_decode_csd(1, ivar->raw_csd, &ivar->csd); - printf("SD CARD: %lld bytes\n", (long long) - ivar->csd.capacity); + if (ivar->csd.csd_structure > 0) + ivar->high_cap = 1; + ivar->tran_speed = ivar->csd.tran_speed; + /* Get card SCR. Card must be selected to fetch it. */ + mmc_select_card(sc, ivar->rca); + mmc_app_send_scr(sc, ivar->rca, ivar->raw_scr); + mmc_app_decode_scr(ivar->raw_scr, &ivar->scr); + /* Get card switch capabilities. */ + if ((ivar->scr.sda_vsn >= 1) && + (ivar->csd.ccc & (1<<10))) { + mmc_sd_switch(sc, 0, 0, 0xF, switch_res); + if (switch_res[13] & 2) { + ivar->timing = bus_timing_hs; + ivar->hs_tran_speed = 50000000; + } + } + mmc_select_card(sc, 0); + /* Find max supported bus width. */ + if ((mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) && + (ivar->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) + ivar->bus_width = bus_width_4; + /* Add device. */ child = device_add_child(sc->dev, NULL, -1); device_set_ivars(child, ivar); return; } - panic("Write MMC card code here"); + mmc_decode_cid(0, ivar->raw_cid, &ivar->cid); + ivar->rca = rca++; + mmc_set_relative_addr(sc, ivar->rca); + /* Get card CSD. */ + mmc_send_csd(sc, ivar->rca, ivar->raw_csd); + mmc_decode_csd(0, ivar->raw_csd, &ivar->csd); + ivar->tran_speed = ivar->csd.tran_speed; + /* Only MMC >= 4.x cards support EXT_CSD. */ + if (ivar->csd.spec_vers >= 4) { + /* Card must be selected to fetch EXT_CSD. */ + mmc_select_card(sc, ivar->rca); + mmc_send_ext_csd(sc, ivar->raw_ext_csd); + /* Get card speed in high speed mode. */ + ivar->timing = bus_timing_hs; + if (((uint8_t *)(ivar->raw_ext_csd))[EXT_CSD_CARD_TYPE] + & EXT_CSD_CARD_TYPE_52) + ivar->hs_tran_speed = 52000000; + else if (((uint8_t *)(ivar->raw_ext_csd))[EXT_CSD_CARD_TYPE] + & EXT_CSD_CARD_TYPE_26) + ivar->hs_tran_speed = 26000000; + else + ivar->hs_tran_speed = ivar->tran_speed; + /* Find max supported bus width. */ + ivar->bus_width = mmc_test_bus_width(sc); + mmc_select_card(sc, 0); + } else { + ivar->bus_width = bus_width_1; + ivar->timing = bus_timing_normal; + } + /* Add device. */ + child = device_add_child(sc->dev, NULL, -1); + device_set_ivars(child, ivar); } free(ivar, M_DEVBUF); } @@ -661,6 +1093,7 @@ mmc_go_discovery(struct mmc_softc *sc) { uint32_t ocr; device_t dev; + int err; dev = sc->dev; if (mmcbr_get_power_mode(dev) != power_on) { @@ -671,7 +1104,9 @@ mmc_go_discovery(struct mmc_softc *sc) mmc_power_up(sc); mmcbr_set_bus_mode(dev, pushpull); mmc_idle_cards(sc); - if (mmc_send_app_op_cond(sc, 0, &ocr) != MMC_ERR_NONE) { + err = mmc_send_if_cond(sc, 1); + if (mmc_send_app_op_cond(sc, err?0:MMC_OCR_CCS, &ocr) != + MMC_ERR_NONE) { /* * Failed, try MMC */ @@ -697,9 +1132,11 @@ mmc_go_discovery(struct mmc_softc *sc) /* * Reselect the cards after we've idled them above. */ - if (mmcbr_get_mode(dev) == mode_sd) - mmc_send_app_op_cond(sc, mmcbr_get_ocr(dev), NULL); - else + if (mmcbr_get_mode(dev) == mode_sd) { + err = mmc_send_if_cond(sc, 1); + mmc_send_app_op_cond(sc, + (err?0:MMC_OCR_CCS)|mmcbr_get_ocr(dev), NULL); + } else mmc_send_op_cond(sc, mmcbr_get_ocr(dev), NULL); mmc_discover_cards(sc); @@ -712,22 +1149,47 @@ mmc_go_discovery(struct mmc_softc *sc) static int mmc_calculate_clock(struct mmc_softc *sc) { - int max_dtr = 0; + int max_dtr, max_hs_dtr, max_timing; int nkid, i, f_min, f_max; device_t *kids; + struct mmc_ivars *ivar; f_min = mmcbr_get_f_min(sc->dev); f_max = mmcbr_get_f_max(sc->dev); - max_dtr = f_max; + max_dtr = max_hs_dtr = f_max; + if ((mmcbr_get_caps(sc->dev) & MMC_CAP_HSPEED)) + max_timing = bus_timing_hs; + else + max_timing = bus_timing_normal; if (device_get_children(sc->dev, &kids, &nkid) != 0) panic("can't get children"); - for (i = 0; i < nkid; i++) - if (mmc_get_tran_speed(kids[i]) < max_dtr) - max_dtr = mmc_get_tran_speed(kids[i]); + for (i = 0; i < nkid; i++) { + ivar = device_get_ivars(kids[i]); + if (ivar->timing < max_timing) + max_timing = ivar->timing; + if (ivar->tran_speed < max_dtr) + max_dtr = ivar->tran_speed; + if (ivar->hs_tran_speed < max_dtr) + max_hs_dtr = ivar->hs_tran_speed; + } + for (i = 0; i < nkid; i++) { + ivar = device_get_ivars(kids[i]); + if (ivar->timing == bus_timing_normal) + continue; + mmc_select_card(sc, ivar->rca); + mmc_set_timing(sc, max_timing); + } + mmc_select_card(sc, 0); free(kids, M_TEMP); - device_printf(sc->dev, "setting transfer rate to %d.%03dMHz\n", - max_dtr / 1000000, (max_dtr / 1000) % 1000); - return (max_dtr); + if (max_timing == bus_timing_hs) + max_dtr = max_hs_dtr; + device_printf(sc->dev, "setting transfer rate to %d.%03dMHz%s\n", + max_dtr / 1000000, (max_dtr / 1000) % 1000, + (max_timing == bus_timing_hs)?" with high speed timing":""); + mmcbr_set_timing(sc->dev, max_timing); + mmcbr_set_clock(sc->dev, max_dtr); + mmcbr_update_ios(sc->dev); + return max_dtr; } static void @@ -741,8 +1203,7 @@ mmc_scan(struct mmc_softc *sc) if (mmcbr_get_power_mode(dev) == power_on) mmc_rescan_cards(sc); mmc_go_discovery(sc); - mmcbr_set_clock(dev, mmc_calculate_clock(sc)); - mmcbr_update_ios(dev); + mmc_calculate_clock(sc); mmc_release_bus(dev, dev); /* XXX probe/attach/detach children? */ @@ -774,6 +1235,9 @@ mmc_read_ivar(device_t bus, device_t chi case MMC_IVAR_READ_ONLY: *(int *)result = ivar->read_only; break; + case MMC_IVAR_HIGH_CAP: + *(int *)result = ivar->high_cap; + break; } return (0); } @@ -824,4 +1288,4 @@ static devclass_t mmc_devclass; DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, 0, 0); -DRIVER_MODULE(mmc, sdh, mmc_driver, mmc_devclass, 0, 0); +DRIVER_MODULE(mmc, sdhci, mmc_driver, mmc_devclass, 0, 0); Modified: user/peter/long_cpumask/sys/dev/mmc/mmcbrvar.h ============================================================================== --- user/peter/long_cpumask/sys/dev/mmc/mmcbrvar.h Wed Oct 8 21:46:17 2008 (r183712) +++ user/peter/long_cpumask/sys/dev/mmc/mmcbrvar.h Thu Oct 9 01:34:27 2008 (r183713) @@ -71,6 +71,7 @@ enum mmcbr_device_ivars { MMCBR_IVAR_POWER_MODE, MMCBR_IVAR_VDD, MMCBR_IVAR_CAPS, + MMCBR_IVAR_TIMING, // MMCBR_IVAR_, }; @@ -92,6 +93,7 @@ MMCBR_ACCESSOR(ocr, OCR, int) MMCBR_ACCESSOR(power_mode, POWER_MODE, int) MMCBR_ACCESSOR(vdd, VDD, int) MMCBR_ACCESSOR(caps, CAPS, int) +MMCBR_ACCESSOR(timing, TIMING, int) static int __inline mmcbr_update_ios(device_t dev) Modified: user/peter/long_cpumask/sys/dev/mmc/mmcreg.h ============================================================================== --- user/peter/long_cpumask/sys/dev/mmc/mmcreg.h Wed Oct 8 21:46:17 2008 (r183712) +++ user/peter/long_cpumask/sys/dev/mmc/mmcreg.h Thu Oct 9 01:34:27 2008 (r183713) @@ -86,7 +86,7 @@ struct mmc_command { #define MMC_RSP_R2 (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC) #define MMC_RSP_R3 (MMC_RSP_PRESENT) #define MMC_RSP_R6 (MMC_RSP_PRESENT | MMC_RSP_CRC) -/* R7 -- new in sd 2.0 */ +#define MMC_RSP_R7 (MMC_RSP_PRESENT | MMC_RSP_CRC) #define MMC_RSP(x) ((x) & MMC_RSP_MASK) uint32_t retries; uint32_t error; @@ -181,16 +181,23 @@ struct mmc_request { #define SD_SEND_RELATIVE_ADDR 3 #define MMC_SET_DSR 4 /* reserved: 5 */ +#define MMC_SWITCH_FUNC 6 +#define MMC_SWITCH_FUNC_CMDS 0 +#define MMC_SWITCH_FUNC_SET 1 +#define MMC_SWITCH_FUNC_CLR 2 +#define MMC_SWITCH_FUNC_WR 3 #define MMC_SELECT_CARD 7 #define MMC_DESELECT_CARD 7 -#define MMC_SEND_IF_COND 8 +#define MMC_SEND_EXT_CSD 8 +#define SD_SEND_IF_COND 8 #define MMC_SEND_CSD 9 #define MMC_SEND_CID 10 #define MMC_READ_DAT_UNTIL_STOP 11 #define MMC_STOP_TRANSMISSION 12 #define MMC_SEND_STATUS 13 - /* reserved: 14 */ +#define MMC_BUSTEST_R 14 #define MMC_GO_INACTIVE_STATE 15 +#define MMC_BUSTEST_W 19 /* Class 2: Block oriented read commands */ #define MMC_SET_BLOCKLEN 16 @@ -277,6 +284,37 @@ struct mmc_request { #define ACMD_SET_CLR_CARD_DETECT 42 #define ACMD_SEND_SCR 51 +/* + * EXT_CSD fields + */ + +#define EXT_CSD_BUS_WIDTH 183 /* R/W */ +#define EXT_CSD_HS_TIMING 185 /* R/W */ +#define EXT_CSD_CARD_TYPE 196 /* RO */ +#define EXT_CSD_REV 192 /* RO */ +#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ + +/* + * EXT_CSD field definitions + */ + +#define EXT_CSD_CMD_SET_NORMAL 1 +#define EXT_CSD_CMD_SET_SECURE 2 +#define EXT_CSD_CMD_SET_CPSECURE 4 + +#define EXT_CSD_CARD_TYPE_26 1 +#define EXT_CSD_CARD_TYPE_52 2 + +#define EXT_CSD_BUS_WIDTH_1 0 +#define EXT_CSD_BUS_WIDTH_4 1 +#define EXT_CSD_BUS_WIDTH_8 2 + +/* + * SD bus widths + */ +#define SD_BUS_WIDTH_1 0 +#define SD_BUS_WIDTH_4 2 + /* OCR bits */ /* @@ -328,6 +366,7 @@ struct mmc_cid { struct mmc_csd { uint8_t csd_structure; + uint8_t spec_vers; uint16_t ccc; uint16_t tacc; uint32_t nsac; @@ -351,6 +390,14 @@ struct mmc_csd wp_grp_enable:1; }; +struct mmc_scr +{ + unsigned char sda_vsn; + unsigned char bus_widths; +#define SD_SCR_BUS_WIDTH_1 (1<<0) +#define SD_SCR_BUS_WIDTH_4 (1<<2) +}; + /* * Older versions of the MMC standard had a variable sector size. However, * I've been able to find no old MMC or SD cards that have a non 512 Modified: user/peter/long_cpumask/sys/dev/mmc/mmcsd.c ============================================================================== --- user/peter/long_cpumask/sys/dev/mmc/mmcsd.c Wed Oct 8 21:46:17 2008 (r183712) +++ user/peter/long_cpumask/sys/dev/mmc/mmcsd.c Thu Oct 9 01:34:27 2008 (r183713) @@ -106,6 +106,7 @@ static int mmcsd_probe(device_t dev) { + device_quiet(dev); device_set_desc(dev, "MMC/SD Memory Card"); return (0); } @@ -256,7 +257,9 @@ mmcsd_task(void *arg) else cmd.opcode = MMC_WRITE_BLOCK; } - cmd.arg = block << 9; + cmd.arg = block; + if (!mmc_get_high_cap(dev)) + cmd.arg <<= 9; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; data.data = vaddr; data.mrq = &req; Modified: user/peter/long_cpumask/sys/dev/mmc/mmcvar.h ============================================================================== --- user/peter/long_cpumask/sys/dev/mmc/mmcvar.h Wed Oct 8 21:46:17 2008 (r183712) +++ user/peter/long_cpumask/sys/dev/mmc/mmcvar.h Thu Oct 9 01:34:27 2008 (r183713) @@ -62,6 +62,7 @@ enum mmc_device_ivars { MMC_IVAR_SECTOR_SIZE, MMC_IVAR_TRAN_SPEED, MMC_IVAR_READ_ONLY, + MMC_IVAR_HIGH_CAP, // MMC_IVAR_, }; @@ -77,5 +78,6 @@ MMC_ACCESSOR(rca, RCA, int) MMC_ACCESSOR(sector_size, SECTOR_SIZE, int) MMC_ACCESSOR(tran_speed, TRAN_SPEED, int) MMC_ACCESSOR(read_only, READ_ONLY, int) +MMC_ACCESSOR(high_cap, HIGH_CAP, int) #endif /* DEV_MMC_MMCVAR_H */ Modified: user/peter/long_cpumask/sys/dev/sio/sio.c ============================================================================== --- user/peter/long_cpumask/sys/dev/sio/sio.c Wed Oct 8 21:46:17 2008 (r183712) +++ user/peter/long_cpumask/sys/dev/sio/sio.c Thu Oct 9 01:34:27 2008 (r183713) @@ -696,6 +696,14 @@ sioprobe(dev, xrid, rclk, noprobe) bus_release_resource(dev, SYS_RES_IOPORT, rid, port); if (iobase == siocniobase) result = 0; + /* + * XXX: Since we don't return 0, we shouldn't be relying on + * the softc that we set to persist to the call to attach + * since other probe routines may be called, and the malloc + * here causes subr_bus to not allocate anything for the + * other probes. Instead, this softc is preserved and other + * probe routines can corrupt it. + */ if (result != 0) { device_set_softc(dev, NULL); free(com, M_DEVBUF); @@ -773,6 +781,13 @@ sioprobe(dev, xrid, rclk, noprobe) bus_release_resource(dev, SYS_RES_IOPORT, rid, port); if (iobase == siocniobase) result = 0; + /* + * XXX: Since we don't return 0, we shouldn't be relying on the softc + * that we set to persist to the call to attach since other probe + * routines may be called, and the malloc here causes subr_bus to not + * allocate anything for the other probes. Instead, this softc is + * preserved and other probe routines can corrupt it. + */ if (result != 0) { device_set_softc(dev, NULL); free(com, M_DEVBUF); Modified: user/peter/long_cpumask/sys/dev/usb/umass.c ============================================================================== --- user/peter/long_cpumask/sys/dev/usb/umass.c Wed Oct 8 21:46:17 2008 (r183712) +++ user/peter/long_cpumask/sys/dev/usb/umass.c Thu Oct 9 01:34:27 2008 (r183713) @@ -610,6 +610,10 @@ static struct umass_devdescr_t umass_dev UMASS_PROTO_SCSI, NO_QUIRKS }, + { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_SDS_HOTFIND_D, RID_WILDCARD, + UMASS_PROTO_SCSI | UMASS_PROTO_BBB, + NO_GETMAXLUN | NO_SYNCHRONIZE_CACHE + }, { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_MDCFE_B_CF_READER, RID_WILDCARD, UMASS_PROTO_SCSI, NO_QUIRKS Modified: user/peter/long_cpumask/sys/dev/usb/usbdevs ============================================================================== --- user/peter/long_cpumask/sys/dev/usb/usbdevs Wed Oct 8 21:46:17 2008 (r183712) +++ user/peter/long_cpumask/sys/dev/usb/usbdevs Thu Oct 9 01:34:27 2008 (r183713) @@ -1855,6 +1855,7 @@ product OMNIVISION OV511 0x0511 OV511 Ca product OMNIVISION OV511PLUS 0xa511 OV511+ Camera /* OnSpec Electronic, Inc. */ +product ONSPEC SDS_HOTFIND_D 0x0400 SDS-infrared.com Hotfind-D Infrared Camera product ONSPEC MDCFE_B_CF_READER 0xa000 MDCFE-B USB CF Reader product ONSPEC CFMS_RW 0xa001 SIIG/Datafab Memory Stick+CF Reader/Writer product ONSPEC READER 0xa003 Datafab-based Reader Modified: user/peter/long_cpumask/sys/kern/imgact_elf.c ============================================================================== --- user/peter/long_cpumask/sys/kern/imgact_elf.c Wed Oct 8 21:46:17 2008 (r183712) +++ user/peter/long_cpumask/sys/kern/imgact_elf.c Thu Oct 9 01:34:27 2008 (r183713) @@ -813,7 +813,8 @@ __CONCAT(exec_, __elfN(imgact))(struct i if (!have_interp && newinterp != NULL) { error = __elfN(load_file)(imgp->proc, newinterp, &addr, &imgp->entry_addr, sv->sv_pagesize); - have_interp = TRUE; + if (error == 0) + have_interp = TRUE; } if (!have_interp) { error = __elfN(load_file)(imgp->proc, interp, &addr, Modified: user/peter/long_cpumask/sys/kern/uipc_usrreq.c ============================================================================== --- user/peter/long_cpumask/sys/kern/uipc_usrreq.c Wed Oct 8 21:46:17 2008 (r183712) +++ user/peter/long_cpumask/sys/kern/uipc_usrreq.c Thu Oct 9 01:34:27 2008 (r183713) @@ -249,20 +249,20 @@ static struct mbuf *unp_addsockcred(stru * Definitions of protocols supported in the LOCAL domain. */ static struct domain localdomain; -static struct pr_usrreqs uipc_usrreqs; +static struct pr_usrreqs uipc_usrreqs_dgram, uipc_usrreqs_stream; static struct protosw localsw[] = { { .pr_type = SOCK_STREAM, .pr_domain = &localdomain, .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_RIGHTS, .pr_ctloutput = &uipc_ctloutput, - .pr_usrreqs = &uipc_usrreqs + .pr_usrreqs = &uipc_usrreqs_stream }, { .pr_type = SOCK_DGRAM, .pr_domain = &localdomain, .pr_flags = PR_ATOMIC|PR_ADDR|PR_RIGHTS, - .pr_usrreqs = &uipc_usrreqs + .pr_usrreqs = &uipc_usrreqs_dgram }, }; @@ -996,7 +996,7 @@ uipc_sockaddr(struct socket *so, struct return (0); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***