Deleted Added
full compact
mmcsd.c (183805) mmcsd.c (184033)
1/*-
2 * Copyright (c) 2006 Bernd Walter. All rights reserved.
3 * Copyright (c) 2006 M. Warner Losh. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 37 unchanged lines hidden (view full) ---

46 * implication, estoppel or otherwise under any patent or other rights of the
47 * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing
48 * herein shall be construed as an obligation by the SD Group, the SD-3C LLC
49 * or the SD Card Association to disclose or distribute any technical
50 * information, know-how or other confidential information to any third party.
51 */
52
53#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2006 Bernd Walter. All rights reserved.
3 * Copyright (c) 2006 M. Warner Losh. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 37 unchanged lines hidden (view full) ---

46 * implication, estoppel or otherwise under any patent or other rights of the
47 * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing
48 * herein shall be construed as an obligation by the SD Group, the SD-3C LLC
49 * or the SD Card Association to disclose or distribute any technical
50 * information, know-how or other confidential information to any third party.
51 */
52
53#include <sys/cdefs.h>
54__FBSDID("$FreeBSD: head/sys/dev/mmc/mmcsd.c 183805 2008-10-12 19:19:26Z mav $");
54__FBSDID("$FreeBSD: head/sys/dev/mmc/mmcsd.c 184033 2008-10-18 16:17:04Z mav $");
55
56#include <sys/param.h>
57#include <sys/systm.h>
58#include <sys/bio.h>
59#include <sys/bus.h>
60#include <sys/conf.h>
61#include <sys/kernel.h>
62#include <sys/kthread.h>

--- 65 unchanged lines hidden (view full) ---

128
129 d = sc->disk = disk_alloc();
130 d->d_open = mmcsd_open;
131 d->d_close = mmcsd_close;
132 d->d_strategy = mmcsd_strategy;
133 // d->d_dump = mmcsd_dump; Need polling mmc layer
134 d->d_name = "mmcsd";
135 d->d_drv1 = sc;
55
56#include <sys/param.h>
57#include <sys/systm.h>
58#include <sys/bio.h>
59#include <sys/bus.h>
60#include <sys/conf.h>
61#include <sys/kernel.h>
62#include <sys/kthread.h>

--- 65 unchanged lines hidden (view full) ---

128
129 d = sc->disk = disk_alloc();
130 d->d_open = mmcsd_open;
131 d->d_close = mmcsd_close;
132 d->d_strategy = mmcsd_strategy;
133 // d->d_dump = mmcsd_dump; Need polling mmc layer
134 d->d_name = "mmcsd";
135 d->d_drv1 = sc;
136 d->d_maxsize = MAXPHYS; /* Maybe ask bridge? */
136 d->d_maxsize = 4*1024*1024; /* Maximum defined SD card AU size. */
137 d->d_sectorsize = mmc_get_sector_size(dev);
138 d->d_mediasize = mmc_get_media_size(dev) * d->d_sectorsize;
139 d->d_unit = device_get_unit(dev);
137 d->d_sectorsize = mmc_get_sector_size(dev);
138 d->d_mediasize = mmc_get_media_size(dev) * d->d_sectorsize;
139 d->d_unit = device_get_unit(dev);
140 d->d_flags = DISKFLAG_CANDELETE;
140 /*
141 * Display in most natural units. There's no cards < 1MB.
142 * The SD standard goes to 2GiB, but the data format supports
143 * up to 4GiB and some card makers push it up to this limit.
144 * The SDHC standard only goes to 32GiB (the data format in
145 * SDHC is good to 2TiB however, which isn't too ugly at
146 * 2048GiBm, so we note it in passing here and don't add the
147 * code to print TiB).

--- 63 unchanged lines hidden (view full) ---

211
212 sc = (struct mmcsd_softc *)bp->bio_disk->d_drv1;
213 MMCSD_LOCK(sc);
214 bioq_disksort(&sc->bio_queue, bp);
215 wakeup(sc);
216 MMCSD_UNLOCK(sc);
217}
218
141 /*
142 * Display in most natural units. There's no cards < 1MB.
143 * The SD standard goes to 2GiB, but the data format supports
144 * up to 4GiB and some card makers push it up to this limit.
145 * The SDHC standard only goes to 32GiB (the data format in
146 * SDHC is good to 2TiB however, which isn't too ugly at
147 * 2048GiBm, so we note it in passing here and don't add the
148 * code to print TiB).

--- 63 unchanged lines hidden (view full) ---

212
213 sc = (struct mmcsd_softc *)bp->bio_disk->d_drv1;
214 MMCSD_LOCK(sc);
215 bioq_disksort(&sc->bio_queue, bp);
216 wakeup(sc);
217 MMCSD_UNLOCK(sc);
218}
219
220static daddr_t
221mmcsd_rw(struct mmcsd_softc *sc, struct bio *bp)
222{
223 daddr_t block, end;
224 struct mmc_command cmd;
225 struct mmc_command stop;
226 struct mmc_request req;
227 struct mmc_data data;
228 device_t dev = sc->dev;
229 int sz = sc->disk->d_sectorsize;
230
231 block = bp->bio_pblkno;
232 end = bp->bio_pblkno + (bp->bio_bcount / sz);
233 while (block < end) {
234 char *vaddr = bp->bio_data +
235 (block - bp->bio_pblkno) * sz;
236 int numblocks;
237#ifdef MULTI_BLOCK
238 numblocks = end - block;
239#else
240 numblocks = 1;
241#endif
242 memset(&req, 0, sizeof(req));
243 memset(&cmd, 0, sizeof(cmd));
244 memset(&stop, 0, sizeof(stop));
245 req.cmd = &cmd;
246 cmd.data = &data;
247 if (bp->bio_cmd == BIO_READ) {
248 if (numblocks > 1)
249 cmd.opcode = MMC_READ_MULTIPLE_BLOCK;
250 else
251 cmd.opcode = MMC_READ_SINGLE_BLOCK;
252 } else {
253 if (numblocks > 1)
254 cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK;
255 else
256 cmd.opcode = MMC_WRITE_BLOCK;
257 }
258 cmd.arg = block;
259 if (!mmc_get_high_cap(dev))
260 cmd.arg <<= 9;
261 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
262 data.data = vaddr;
263 data.mrq = &req;
264 if (bp->bio_cmd == BIO_READ)
265 data.flags = MMC_DATA_READ;
266 else
267 data.flags = MMC_DATA_WRITE;
268 data.len = numblocks * sz;
269 if (numblocks > 1) {
270 data.flags |= MMC_DATA_MULTI;
271 stop.opcode = MMC_STOP_TRANSMISSION;
272 stop.arg = 0;
273 stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
274 req.stop = &stop;
275 }
276// printf("Len %d %lld-%lld flags %#x sz %d\n",
277// (int)data.len, (long long)block, (long long)end, data.flags, sz);
278 MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
279 &req);
280 if (req.cmd->error != MMC_ERR_NONE)
281 break;
282 block += numblocks;
283 }
284 return (block);
285}
286
287static daddr_t
288mmcsd_delete(struct mmcsd_softc *sc, struct bio *bp)
289{
290 daddr_t block, end, start, stop;
291 struct mmc_command cmd;
292 struct mmc_request req;
293 device_t dev = sc->dev;
294 int sz = sc->disk->d_sectorsize;
295 int erase_sector;
296
297 block = bp->bio_pblkno;
298 end = bp->bio_pblkno + (bp->bio_bcount / sz);
299
300 /* Safe round to the erase sector boundaries. */
301 erase_sector = mmc_get_erase_sector(dev);
302 start = block + erase_sector - 1; /* Round up. */
303 start -= start % erase_sector;
304 stop = end; /* Round down. */
305 stop -= end % erase_sector;
306
307 /* We can't erase areas smaller then sector. */
308 if (start >= stop)
309 return (end);
310
311 /* Set erase start position. */
312 memset(&req, 0, sizeof(req));
313 memset(&cmd, 0, sizeof(cmd));
314 req.cmd = &cmd;
315 if (mmc_get_card_type(dev) == mode_sd)
316 cmd.opcode = SD_ERASE_WR_BLK_START;
317 else
318 cmd.opcode = MMC_ERASE_GROUP_START;
319 cmd.arg = start;
320 if (!mmc_get_high_cap(dev))
321 cmd.arg <<= 9;
322 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
323 MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
324 &req);
325 if (req.cmd->error != MMC_ERR_NONE) {
326 printf("erase err1: %d\n", req.cmd->error);
327 return (block);
328 }
329 /* Set erase stop position. */
330 memset(&req, 0, sizeof(req));
331 memset(&cmd, 0, sizeof(cmd));
332 req.cmd = &cmd;
333 if (mmc_get_card_type(dev) == mode_sd)
334 cmd.opcode = SD_ERASE_WR_BLK_END;
335 else
336 cmd.opcode = MMC_ERASE_GROUP_END;
337 cmd.arg = stop;
338 if (!mmc_get_high_cap(dev))
339 cmd.arg <<= 9;
340 cmd.arg--;
341 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
342 MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
343 &req);
344 if (req.cmd->error != MMC_ERR_NONE) {
345 printf("erase err2: %d\n", req.cmd->error);
346 return (block);
347 }
348 /* Erase range. */
349 memset(&req, 0, sizeof(req));
350 memset(&cmd, 0, sizeof(cmd));
351 req.cmd = &cmd;
352 cmd.opcode = MMC_ERASE;
353 cmd.arg = 0;
354 cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
355 MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
356 &req);
357 if (req.cmd->error != MMC_ERR_NONE) {
358 printf("erase err3 %d\n", req.cmd->error);
359 return (block);
360 }
361
362 return (end);
363}
364
219static void
220mmcsd_task(void *arg)
221{
222 struct mmcsd_softc *sc = (struct mmcsd_softc*)arg;
223 struct bio *bp;
224 int sz;
225 daddr_t block, end;
365static void
366mmcsd_task(void *arg)
367{
368 struct mmcsd_softc *sc = (struct mmcsd_softc*)arg;
369 struct bio *bp;
370 int sz;
371 daddr_t block, end;
226 struct mmc_command cmd;
227 struct mmc_command stop;
228 struct mmc_request req;
229 struct mmc_data data;
230 device_t dev;
231
232 dev = sc->dev;
233 while (sc->running) {
234 MMCSD_LOCK(sc);
235 do {
236 bp = bioq_first(&sc->bio_queue);
237 if (bp == NULL)
238 msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0);
239 } while (bp == NULL && sc->running);
240 if (bp)
241 bioq_remove(&sc->bio_queue, bp);
242 MMCSD_UNLOCK(sc);
243 if (!sc->running)
244 break;
372 device_t dev;
373
374 dev = sc->dev;
375 while (sc->running) {
376 MMCSD_LOCK(sc);
377 do {
378 bp = bioq_first(&sc->bio_queue);
379 if (bp == NULL)
380 msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0);
381 } while (bp == NULL && sc->running);
382 if (bp)
383 bioq_remove(&sc->bio_queue, bp);
384 MMCSD_UNLOCK(sc);
385 if (!sc->running)
386 break;
245// printf("mmc_task: request %p for block %ju\n", bp, bp->bio_pblkno);
246 if (bp->bio_cmd != BIO_READ && mmc_get_read_only(dev)) {
247 bp->bio_error = EROFS;
248 bp->bio_resid = bp->bio_bcount;
249 bp->bio_flags |= BIO_ERROR;
250 biodone(bp);
251 continue;
252 }
253 MMCBUS_ACQUIRE_BUS(device_get_parent(dev), dev);
254 sz = sc->disk->d_sectorsize;
387 if (bp->bio_cmd != BIO_READ && mmc_get_read_only(dev)) {
388 bp->bio_error = EROFS;
389 bp->bio_resid = bp->bio_bcount;
390 bp->bio_flags |= BIO_ERROR;
391 biodone(bp);
392 continue;
393 }
394 MMCBUS_ACQUIRE_BUS(device_get_parent(dev), dev);
395 sz = sc->disk->d_sectorsize;
396 block = bp->bio_pblkno;
255 end = bp->bio_pblkno + (bp->bio_bcount / sz);
397 end = bp->bio_pblkno + (bp->bio_bcount / sz);
256 for (block = bp->bio_pblkno; block < end;) {
257 char *vaddr = bp->bio_data + (block - bp->bio_pblkno) * sz;
258 int numblocks;
259#ifdef MULTI_BLOCK
260 numblocks = end - block;
261#else
262 numblocks = 1;
263#endif
264 memset(&req, 0, sizeof(req));
265 memset(&cmd, 0, sizeof(cmd));
266 memset(&stop, 0, sizeof(stop));
267 req.cmd = &cmd;
268 cmd.data = &data;
269 if (bp->bio_cmd == BIO_READ) {
270 if (numblocks > 1)
271 cmd.opcode = MMC_READ_MULTIPLE_BLOCK;
272 else
273 cmd.opcode = MMC_READ_SINGLE_BLOCK;
274 } else {
275 if (numblocks > 1)
276 cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK;
277 else
278 cmd.opcode = MMC_WRITE_BLOCK;
279 }
280 cmd.arg = block;
281 if (!mmc_get_high_cap(dev))
282 cmd.arg <<= 9;
283 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
284 data.data = vaddr;
285 data.mrq = &req;
286 if (bp->bio_cmd == BIO_READ)
287 data.flags = MMC_DATA_READ;
288 else
289 data.flags = MMC_DATA_WRITE;
290 data.len = numblocks * sz;
291 if (numblocks > 1) {
292 data.flags |= MMC_DATA_MULTI;
293 stop.opcode = MMC_STOP_TRANSMISSION;
294 stop.arg = 0;
295 stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
296 req.stop = &stop;
297 }
298// printf("Len %d %lld-%lld flags %#x sz %d\n",
299// (int)data.len, (long long)block, (long long)end, data.flags, sz);
300 MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
301 &req);
302 if (req.cmd->error != MMC_ERR_NONE)
303 break;
304 block += numblocks;
398 if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
399 block = mmcsd_rw(sc, bp);
400 } else if (bp->bio_cmd == BIO_DELETE) {
401 block = mmcsd_delete(sc, bp);
402 } else {
403 /* UNSUPPORTED COMMAND */
404 block = bp->bio_pblkno;
305 }
306 MMCBUS_RELEASE_BUS(device_get_parent(dev), dev);
307 if (block < end) {
308 bp->bio_error = EIO;
309 bp->bio_resid = (end - block) * sz;
310 bp->bio_flags |= BIO_ERROR;
311 }
312 biodone(bp);

--- 46 unchanged lines hidden ---
405 }
406 MMCBUS_RELEASE_BUS(device_get_parent(dev), dev);
407 if (block < end) {
408 bp->bio_error = EIO;
409 bp->bio_resid = (end - block) * sz;
410 bp->bio_flags |= BIO_ERROR;
411 }
412 biodone(bp);

--- 46 unchanged lines hidden ---