ps3disk.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. /*-
  2. * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  3. *
  4. * Copyright (C) 2011 glevand (geoffrey.levand@mail.ru)
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  17. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  18. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  19. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  21. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  23. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  25. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. *
  27. */
  28. #include <sys/cdefs.h>
  29. __FBSDID("$FreeBSD$");
  30. #include <sys/param.h>
  31. #include <sys/systm.h>
  32. #include <sys/sysctl.h>
  33. #include <sys/disk.h>
  34. #include <sys/bio.h>
  35. #include <sys/bus.h>
  36. #include <sys/conf.h>
  37. #include <sys/kernel.h>
  38. #include <sys/kthread.h>
  39. #include <sys/lock.h>
  40. #include <sys/malloc.h>
  41. #include <sys/module.h>
  42. #include <sys/mutex.h>
  43. #include <vm/vm.h>
  44. #include <vm/pmap.h>
  45. #include <machine/pio.h>
  46. #include <machine/bus.h>
  47. #include <machine/platform.h>
  48. #include <machine/resource.h>
  49. #include <sys/bus.h>
  50. #include <sys/rman.h>
  51. #include <geom/geom_disk.h>
  52. #include "ps3bus.h"
  53. #include "ps3-hvcall.h"
  54. #define PS3DISK_LOCK_INIT(_sc) \
  55. mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), "ps3disk", MTX_DEF)
  56. #define PS3DISK_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
  57. #define PS3DISK_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
  58. #define PS3DISK_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
  59. #define PS3DISK_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
  60. #define PS3DISK_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
  61. #define LV1_STORAGE_ATA_HDDOUT 0x23
  62. static SYSCTL_NODE(_hw, OID_AUTO, ps3disk, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
  63. "PS3 Disk driver parameters");
  64. #ifdef PS3DISK_DEBUG
  65. static int ps3disk_debug = 0;
  66. SYSCTL_INT(_hw_ps3disk, OID_AUTO, debug, CTLFLAG_RW, &ps3disk_debug,
  67. 0, "control debugging printfs");
  68. TUNABLE_INT("hw.ps3disk.debug", &ps3disk_debug);
  69. enum {
  70. PS3DISK_DEBUG_INTR = 0x00000001,
  71. PS3DISK_DEBUG_TASK = 0x00000002,
  72. PS3DISK_DEBUG_READ = 0x00000004,
  73. PS3DISK_DEBUG_WRITE = 0x00000008,
  74. PS3DISK_DEBUG_FLUSH = 0x00000010,
  75. PS3DISK_DEBUG_ANY = 0xffffffff
  76. };
  77. #define DPRINTF(sc, m, fmt, ...) \
  78. do { \
  79. if (sc->sc_debug & (m)) \
  80. printf(fmt, __VA_ARGS__); \
  81. } while (0)
  82. #else
  83. #define DPRINTF(sc, m, fmt, ...)
  84. #endif
  85. struct ps3disk_region {
  86. uint64_t r_id;
  87. uint64_t r_start;
  88. uint64_t r_size;
  89. uint64_t r_flags;
  90. };
  91. struct ps3disk_softc {
  92. device_t sc_dev;
  93. struct mtx sc_mtx;
  94. uint64_t sc_blksize;
  95. uint64_t sc_nblocks;
  96. uint64_t sc_nregs;
  97. struct ps3disk_region *sc_reg;
  98. int sc_irqid;
  99. struct resource *sc_irq;
  100. void *sc_irqctx;
  101. struct disk **sc_disk;
  102. struct bio_queue_head sc_bioq;
  103. struct bio_queue_head sc_deferredq;
  104. struct proc *sc_task;
  105. bus_dma_tag_t sc_dmatag;
  106. int sc_running;
  107. int sc_debug;
  108. };
  109. static int ps3disk_open(struct disk *dp);
  110. static int ps3disk_close(struct disk *dp);
  111. static void ps3disk_strategy(struct bio *bp);
  112. static void ps3disk_task(void *arg);
  113. static void ps3disk_intr(void *arg);
  114. static int ps3disk_get_disk_geometry(struct ps3disk_softc *sc);
  115. static int ps3disk_enum_regions(struct ps3disk_softc *sc);
  116. static void ps3disk_transfer(void *arg, bus_dma_segment_t *segs, int nsegs,
  117. int error);
  118. static void ps3disk_sysctlattach(struct ps3disk_softc *sc);
  119. static MALLOC_DEFINE(M_PS3DISK, "ps3disk", "PS3 Disk");
  120. static int
  121. ps3disk_probe(device_t dev)
  122. {
  123. if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_STORAGE ||
  124. ps3bus_get_devtype(dev) != PS3_DEVTYPE_DISK)
  125. return (ENXIO);
  126. device_set_desc(dev, "Playstation 3 Disk");
  127. return (BUS_PROBE_SPECIFIC);
  128. }
  129. static int
  130. ps3disk_attach(device_t dev)
  131. {
  132. struct ps3disk_softc *sc;
  133. struct disk *d;
  134. intmax_t mb;
  135. uint64_t junk;
  136. char unit;
  137. int i, err;
  138. sc = device_get_softc(dev);
  139. sc->sc_dev = dev;
  140. PS3DISK_LOCK_INIT(sc);
  141. err = ps3disk_get_disk_geometry(sc);
  142. if (err) {
  143. device_printf(dev, "Could not get disk geometry\n");
  144. err = ENXIO;
  145. goto fail_destroy_lock;
  146. }
  147. device_printf(dev, "block size %lu total blocks %lu\n",
  148. sc->sc_blksize, sc->sc_nblocks);
  149. err = ps3disk_enum_regions(sc);
  150. if (err) {
  151. device_printf(dev, "Could not enumerate disk regions\n");
  152. err = ENXIO;
  153. goto fail_destroy_lock;
  154. }
  155. device_printf(dev, "Found %lu regions\n", sc->sc_nregs);
  156. if (!sc->sc_nregs) {
  157. err = ENXIO;
  158. goto fail_destroy_lock;
  159. }
  160. /* Setup interrupt handler */
  161. sc->sc_irqid = 0;
  162. sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqid,
  163. RF_ACTIVE);
  164. if (!sc->sc_irq) {
  165. device_printf(dev, "Could not allocate IRQ\n");
  166. err = ENXIO;
  167. goto fail_free_regions;
  168. }
  169. err = bus_setup_intr(dev, sc->sc_irq,
  170. INTR_TYPE_BIO | INTR_MPSAFE | INTR_ENTROPY,
  171. NULL, ps3disk_intr, sc, &sc->sc_irqctx);
  172. if (err) {
  173. device_printf(dev, "Could not setup IRQ\n");
  174. err = ENXIO;
  175. goto fail_release_intr;
  176. }
  177. /* Setup DMA */
  178. err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0,
  179. BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
  180. BUS_SPACE_UNRESTRICTED, 1, PAGE_SIZE, 0,
  181. busdma_lock_mutex, &sc->sc_mtx, &sc->sc_dmatag);
  182. if (err) {
  183. device_printf(dev, "Could not create DMA tag\n");
  184. err = ENXIO;
  185. goto fail_teardown_intr;
  186. }
  187. /* Setup disks */
  188. sc->sc_disk = malloc(sc->sc_nregs * sizeof(struct disk *),
  189. M_PS3DISK, M_ZERO | M_WAITOK);
  190. if (!sc->sc_disk) {
  191. device_printf(dev, "Could not allocate disk(s)\n");
  192. err = ENOMEM;
  193. goto fail_teardown_intr;
  194. }
  195. for (i = 0; i < sc->sc_nregs; i++) {
  196. struct ps3disk_region *rp = &sc->sc_reg[i];
  197. d = sc->sc_disk[i] = disk_alloc();
  198. d->d_open = ps3disk_open;
  199. d->d_close = ps3disk_close;
  200. d->d_strategy = ps3disk_strategy;
  201. d->d_name = "ps3disk";
  202. d->d_drv1 = sc;
  203. d->d_maxsize = PAGE_SIZE;
  204. d->d_sectorsize = sc->sc_blksize;
  205. d->d_unit = i;
  206. d->d_mediasize = sc->sc_reg[i].r_size * sc->sc_blksize;
  207. d->d_flags |= DISKFLAG_CANFLUSHCACHE;
  208. mb = d->d_mediasize >> 20;
  209. unit = 'M';
  210. if (mb >= 10240) {
  211. unit = 'G';
  212. mb /= 1024;
  213. }
  214. /* Test to see if we can read this region */
  215. err = lv1_storage_read(ps3bus_get_device(dev), d->d_unit,
  216. 0, 0, rp->r_flags, 0, &junk);
  217. device_printf(dev, "region %d %ju%cB%s\n", i, mb, unit,
  218. (err == LV1_DENIED_BY_POLICY) ? " (hypervisor protected)"
  219. : "");
  220. if (err != LV1_DENIED_BY_POLICY)
  221. disk_create(d, DISK_VERSION);
  222. }
  223. err = 0;
  224. bioq_init(&sc->sc_bioq);
  225. bioq_init(&sc->sc_deferredq);
  226. kproc_create(&ps3disk_task, sc, &sc->sc_task, 0, 0, "ps3disk");
  227. ps3disk_sysctlattach(sc);
  228. sc->sc_running = 1;
  229. return (0);
  230. fail_teardown_intr:
  231. bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
  232. fail_release_intr:
  233. bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
  234. fail_free_regions:
  235. free(sc->sc_reg, M_PS3DISK);
  236. fail_destroy_lock:
  237. PS3DISK_LOCK_DESTROY(sc);
  238. return (err);
  239. }
  240. static int
  241. ps3disk_detach(device_t dev)
  242. {
  243. struct ps3disk_softc *sc = device_get_softc(dev);
  244. int i;
  245. for (i = 0; i < sc->sc_nregs; i++)
  246. disk_destroy(sc->sc_disk[i]);
  247. bus_dma_tag_destroy(sc->sc_dmatag);
  248. bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
  249. bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
  250. free(sc->sc_disk, M_PS3DISK);
  251. free(sc->sc_reg, M_PS3DISK);
  252. PS3DISK_LOCK_DESTROY(sc);
  253. return (0);
  254. }
  255. static int
  256. ps3disk_open(struct disk *dp)
  257. {
  258. return (0);
  259. }
  260. static int
  261. ps3disk_close(struct disk *dp)
  262. {
  263. return (0);
  264. }
  265. /* Process deferred blocks */
  266. static void
  267. ps3disk_task(void *arg)
  268. {
  269. struct ps3disk_softc *sc = (struct ps3disk_softc *) arg;
  270. struct bio *bp;
  271. while (1) {
  272. kproc_suspend_check(sc->sc_task);
  273. tsleep(&sc->sc_deferredq, PRIBIO, "ps3disk", 10);
  274. PS3DISK_LOCK(sc);
  275. bp = bioq_takefirst(&sc->sc_deferredq);
  276. PS3DISK_UNLOCK(sc);
  277. if (bp == NULL)
  278. continue;
  279. if (bp->bio_driver1 != NULL) {
  280. bus_dmamap_unload(sc->sc_dmatag, (bus_dmamap_t)
  281. bp->bio_driver1);
  282. bus_dmamap_destroy(sc->sc_dmatag, (bus_dmamap_t)
  283. bp->bio_driver1);
  284. }
  285. ps3disk_strategy(bp);
  286. }
  287. kproc_exit(0);
  288. }
  289. static void
  290. ps3disk_strategy(struct bio *bp)
  291. {
  292. struct ps3disk_softc *sc = (struct ps3disk_softc *)bp->bio_disk->d_drv1;
  293. int err;
  294. if (sc == NULL) {
  295. bp->bio_flags |= BIO_ERROR;
  296. bp->bio_error = EINVAL;
  297. biodone(bp);
  298. return;
  299. }
  300. PS3DISK_LOCK(sc);
  301. bp->bio_resid = bp->bio_bcount;
  302. bioq_insert_tail(&sc->sc_bioq, bp);
  303. DPRINTF(sc, PS3DISK_DEBUG_TASK, "%s: bio_cmd 0x%02x\n",
  304. __func__, bp->bio_cmd);
  305. err = 0;
  306. if (bp->bio_cmd == BIO_FLUSH) {
  307. bp->bio_driver1 = 0;
  308. err = lv1_storage_send_device_command(
  309. ps3bus_get_device(sc->sc_dev), LV1_STORAGE_ATA_HDDOUT,
  310. 0, 0, 0, 0, (uint64_t *)&bp->bio_driver2);
  311. if (err == LV1_BUSY)
  312. err = EAGAIN;
  313. } else if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
  314. if (bp->bio_bcount % sc->sc_blksize != 0) {
  315. err = EINVAL;
  316. } else {
  317. bus_dmamap_create(sc->sc_dmatag, BUS_DMA_COHERENT,
  318. (bus_dmamap_t *)(&bp->bio_driver1));
  319. err = bus_dmamap_load(sc->sc_dmatag,
  320. (bus_dmamap_t)(bp->bio_driver1), bp->bio_data,
  321. bp->bio_bcount, ps3disk_transfer, bp, 0);
  322. if (err == EINPROGRESS)
  323. err = 0;
  324. }
  325. } else {
  326. err = EINVAL;
  327. }
  328. if (err == EAGAIN) {
  329. bioq_remove(&sc->sc_bioq, bp);
  330. bioq_insert_tail(&sc->sc_deferredq, bp);
  331. } else if (err != 0) {
  332. bp->bio_error = err;
  333. bp->bio_flags |= BIO_ERROR;
  334. bioq_remove(&sc->sc_bioq, bp);
  335. disk_err(bp, "hard error", -1, 1);
  336. biodone(bp);
  337. }
  338. PS3DISK_UNLOCK(sc);
  339. }
  340. static void
  341. ps3disk_intr(void *arg)
  342. {
  343. struct ps3disk_softc *sc = (struct ps3disk_softc *) arg;
  344. device_t dev = sc->sc_dev;
  345. uint64_t devid = ps3bus_get_device(dev);
  346. struct bio *bp;
  347. uint64_t tag, status;
  348. if (lv1_storage_get_async_status(devid, &tag, &status) != 0)
  349. return;
  350. PS3DISK_LOCK(sc);
  351. DPRINTF(sc, PS3DISK_DEBUG_INTR, "%s: tag 0x%016lx "
  352. "status 0x%016lx\n", __func__, tag, status);
  353. /* Locate the matching request */
  354. TAILQ_FOREACH(bp, &sc->sc_bioq.queue, bio_queue) {
  355. if ((uint64_t)bp->bio_driver2 != tag)
  356. continue;
  357. if (status != 0) {
  358. device_printf(sc->sc_dev, "%s error (%#lx)\n",
  359. (bp->bio_cmd == BIO_READ) ? "Read" : "Write",
  360. status);
  361. bp->bio_error = EIO;
  362. bp->bio_flags |= BIO_ERROR;
  363. } else {
  364. bp->bio_error = 0;
  365. bp->bio_resid = 0;
  366. bp->bio_flags |= BIO_DONE;
  367. }
  368. if (bp->bio_driver1 != NULL) {
  369. if (bp->bio_cmd == BIO_READ)
  370. bus_dmamap_sync(sc->sc_dmatag, (bus_dmamap_t)
  371. bp->bio_driver1, BUS_DMASYNC_POSTREAD);
  372. bus_dmamap_unload(sc->sc_dmatag, (bus_dmamap_t)
  373. bp->bio_driver1);
  374. bus_dmamap_destroy(sc->sc_dmatag, (bus_dmamap_t)
  375. bp->bio_driver1);
  376. }
  377. bioq_remove(&sc->sc_bioq, bp);
  378. biodone(bp);
  379. break;
  380. }
  381. if (bioq_first(&sc->sc_deferredq) != NULL)
  382. wakeup(&sc->sc_deferredq);
  383. PS3DISK_UNLOCK(sc);
  384. }
  385. static int
  386. ps3disk_get_disk_geometry(struct ps3disk_softc *sc)
  387. {
  388. device_t dev = sc->sc_dev;
  389. uint64_t bus_index = ps3bus_get_busidx(dev);
  390. uint64_t dev_index = ps3bus_get_devidx(dev);
  391. uint64_t junk;
  392. int err;
  393. err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
  394. (lv1_repository_string("bus") >> 32) | bus_index,
  395. lv1_repository_string("dev") | dev_index,
  396. lv1_repository_string("blk_size"), 0, &sc->sc_blksize, &junk);
  397. if (err) {
  398. device_printf(dev, "Could not get block size (0x%08x)\n", err);
  399. return (ENXIO);
  400. }
  401. err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
  402. (lv1_repository_string("bus") >> 32) | bus_index,
  403. lv1_repository_string("dev") | dev_index,
  404. lv1_repository_string("n_blocks"), 0, &sc->sc_nblocks, &junk);
  405. if (err) {
  406. device_printf(dev, "Could not get total number of blocks "
  407. "(0x%08x)\n", err);
  408. err = ENXIO;
  409. }
  410. return (err);
  411. }
  412. static int
  413. ps3disk_enum_regions(struct ps3disk_softc *sc)
  414. {
  415. device_t dev = sc->sc_dev;
  416. uint64_t bus_index = ps3bus_get_busidx(dev);
  417. uint64_t dev_index = ps3bus_get_devidx(dev);
  418. uint64_t junk;
  419. int i, err;
  420. /* Read number of regions */
  421. err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
  422. (lv1_repository_string("bus") >> 32) | bus_index,
  423. lv1_repository_string("dev") | dev_index,
  424. lv1_repository_string("n_regs"), 0, &sc->sc_nregs, &junk);
  425. if (err) {
  426. device_printf(dev, "Could not get number of regions (0x%08x)\n",
  427. err);
  428. err = ENXIO;
  429. goto fail;
  430. }
  431. if (!sc->sc_nregs)
  432. return 0;
  433. sc->sc_reg = malloc(sc->sc_nregs * sizeof(struct ps3disk_region),
  434. M_PS3DISK, M_ZERO | M_WAITOK);
  435. if (!sc->sc_reg) {
  436. err = ENOMEM;
  437. goto fail;
  438. }
  439. /* Setup regions */
  440. for (i = 0; i < sc->sc_nregs; i++) {
  441. err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
  442. (lv1_repository_string("bus") >> 32) | bus_index,
  443. lv1_repository_string("dev") | dev_index,
  444. lv1_repository_string("region") | i,
  445. lv1_repository_string("id"), &sc->sc_reg[i].r_id, &junk);
  446. if (err) {
  447. device_printf(dev, "Could not get region id (0x%08x)\n",
  448. err);
  449. err = ENXIO;
  450. goto fail;
  451. }
  452. err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
  453. (lv1_repository_string("bus") >> 32) | bus_index,
  454. lv1_repository_string("dev") | dev_index,
  455. lv1_repository_string("region") | i,
  456. lv1_repository_string("start"), &sc->sc_reg[i].r_start,
  457. &junk);
  458. if (err) {
  459. device_printf(dev, "Could not get region start "
  460. "(0x%08x)\n", err);
  461. err = ENXIO;
  462. goto fail;
  463. }
  464. err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
  465. (lv1_repository_string("bus") >> 32) | bus_index,
  466. lv1_repository_string("dev") | dev_index,
  467. lv1_repository_string("region") | i,
  468. lv1_repository_string("size"), &sc->sc_reg[i].r_size,
  469. &junk);
  470. if (err) {
  471. device_printf(dev, "Could not get region size "
  472. "(0x%08x)\n", err);
  473. err = ENXIO;
  474. goto fail;
  475. }
  476. if (i == 0)
  477. sc->sc_reg[i].r_flags = 0x2;
  478. else
  479. sc->sc_reg[i].r_flags = 0;
  480. }
  481. return (0);
  482. fail:
  483. sc->sc_nregs = 0;
  484. if (sc->sc_reg)
  485. free(sc->sc_reg, M_PS3DISK);
  486. return (err);
  487. }
  488. static void
  489. ps3disk_transfer(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
  490. {
  491. struct bio *bp = (struct bio *)(arg);
  492. struct ps3disk_softc *sc = (struct ps3disk_softc *)bp->bio_disk->d_drv1;
  493. struct ps3disk_region *rp = &sc->sc_reg[bp->bio_disk->d_unit];
  494. uint64_t devid = ps3bus_get_device(sc->sc_dev);
  495. uint64_t block;
  496. int i, err;
  497. /* Locks already held by busdma */
  498. PS3DISK_ASSERT_LOCKED(sc);
  499. if (error) {
  500. bp->bio_error = error;
  501. bp->bio_flags |= BIO_ERROR;
  502. bioq_remove(&sc->sc_bioq, bp);
  503. biodone(bp);
  504. return;
  505. }
  506. block = bp->bio_pblkno;
  507. for (i = 0; i < nsegs; i++) {
  508. KASSERT((segs[i].ds_len % sc->sc_blksize) == 0,
  509. ("DMA fragments not blocksize multiples"));
  510. if (bp->bio_cmd == BIO_READ) {
  511. err = lv1_storage_read(devid, rp->r_id,
  512. block, segs[i].ds_len/sc->sc_blksize,
  513. rp->r_flags, segs[i].ds_addr,
  514. (uint64_t *)&bp->bio_driver2);
  515. } else {
  516. bus_dmamap_sync(sc->sc_dmatag,
  517. (bus_dmamap_t)bp->bio_driver1,
  518. BUS_DMASYNC_PREWRITE);
  519. err = lv1_storage_write(devid, rp->r_id,
  520. block, segs[i].ds_len/sc->sc_blksize,
  521. rp->r_flags, segs[i].ds_addr,
  522. (uint64_t *)&bp->bio_driver2);
  523. }
  524. if (err) {
  525. if (err == LV1_BUSY) {
  526. bioq_remove(&sc->sc_bioq, bp);
  527. bioq_insert_tail(&sc->sc_deferredq, bp);
  528. } else {
  529. bus_dmamap_unload(sc->sc_dmatag, (bus_dmamap_t)
  530. bp->bio_driver1);
  531. bus_dmamap_destroy(sc->sc_dmatag, (bus_dmamap_t)
  532. bp->bio_driver1);
  533. device_printf(sc->sc_dev, "Could not read "
  534. "sectors (0x%08x)\n", err);
  535. bp->bio_error = EINVAL;
  536. bp->bio_flags |= BIO_ERROR;
  537. bioq_remove(&sc->sc_bioq, bp);
  538. biodone(bp);
  539. }
  540. break;
  541. }
  542. DPRINTF(sc, PS3DISK_DEBUG_READ, "%s: tag 0x%016lx\n",
  543. __func__, sc->sc_bounce_tag);
  544. }
  545. }
  546. #ifdef PS3DISK_DEBUG
  547. static int
  548. ps3disk_sysctl_debug(SYSCTL_HANDLER_ARGS)
  549. {
  550. struct ps3disk_softc *sc = arg1;
  551. int debug, error;
  552. debug = sc->sc_debug;
  553. error = sysctl_handle_int(oidp, &debug, 0, req);
  554. if (error || !req->newptr)
  555. return error;
  556. sc->sc_debug = debug;
  557. return 0;
  558. }
  559. #endif
  560. static void
  561. ps3disk_sysctlattach(struct ps3disk_softc *sc)
  562. {
  563. #ifdef PS3DISK_DEBUG
  564. struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
  565. struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
  566. sc->sc_debug = ps3disk_debug;
  567. SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
  568. "debug", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0,
  569. ps3disk_sysctl_debug, "I", "control debugging printfs");
  570. #endif
  571. }
  572. static device_method_t ps3disk_methods[] = {
  573. DEVMETHOD(device_probe, ps3disk_probe),
  574. DEVMETHOD(device_attach, ps3disk_attach),
  575. DEVMETHOD(device_detach, ps3disk_detach),
  576. {0, 0},
  577. };
  578. static driver_t ps3disk_driver = {
  579. "ps3disk",
  580. ps3disk_methods,
  581. sizeof(struct ps3disk_softc),
  582. };
  583. static devclass_t ps3disk_devclass;
  584. DRIVER_MODULE(ps3disk, ps3bus, ps3disk_driver, ps3disk_devclass, 0, 0);