1224106Snwhitehorn/*- 2224106Snwhitehorn * Copyright (C) 2011 glevand (geoffrey.levand@mail.ru) 3224106Snwhitehorn * All rights reserved. 4224106Snwhitehorn * 5224106Snwhitehorn * Redistribution and use in source and binary forms, with or without 6224106Snwhitehorn * modification, are permitted provided that the following conditions 7224106Snwhitehorn * are met: 8224106Snwhitehorn * 1. Redistributions of source code must retain the above copyright 9224106Snwhitehorn * notice, this list of conditions and the following disclaimer. 10224106Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 11224106Snwhitehorn * notice, this list of conditions and the following disclaimer in the 12224106Snwhitehorn * documentation and/or other materials provided with the distribution. 13224106Snwhitehorn * 14224106Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15224106Snwhitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16224106Snwhitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17224106Snwhitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18224106Snwhitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19224106Snwhitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20224106Snwhitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21224106Snwhitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22224106Snwhitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23224106Snwhitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24224106Snwhitehorn * 25224106Snwhitehorn * $FreeBSD$ 26224106Snwhitehorn */ 27224106Snwhitehorn 28224106Snwhitehorn#include <stand.h> 29224106Snwhitehorn 30224106Snwhitehorn#include "bootstrap.h" 31224106Snwhitehorn#include "lv1call.h" 32224106Snwhitehorn#include "ps3bus.h" 33224106Snwhitehorn#include "ps3repo.h" 34224106Snwhitehorn#include "ps3stor.h" 35224106Snwhitehorn 36224106Snwhitehornint ps3stor_setup(struct ps3_stordev *sd, int type) 37224106Snwhitehorn{ 38224106Snwhitehorn unsigned int i; 39224106Snwhitehorn int err; 40224106Snwhitehorn 41224106Snwhitehorn sd->sd_type = type; 42224106Snwhitehorn 43224106Snwhitehorn err = ps3repo_find_bus_by_type(PS3_BUS_TYPE_STOR, &sd->sd_busidx); 44224106Snwhitehorn if (err) 45224106Snwhitehorn goto out; 46224106Snwhitehorn 47224106Snwhitehorn err = ps3repo_read_bus_id(sd->sd_busidx, &sd->sd_busid); 48224106Snwhitehorn if (err) 49224106Snwhitehorn goto out; 50224106Snwhitehorn 51224106Snwhitehorn err = ps3repo_find_bus_dev_by_type(sd->sd_busidx, type, &sd->sd_devidx); 52224106Snwhitehorn if (err) 53224106Snwhitehorn goto out; 54224106Snwhitehorn 55224857Snwhitehorn err = ps3repo_read_bus_dev_id(sd->sd_busidx, sd->sd_devidx, 56224857Snwhitehorn &sd->sd_devid); 57224106Snwhitehorn if (err) 58224106Snwhitehorn goto out; 59224106Snwhitehorn 60224857Snwhitehorn err = ps3repo_read_bus_dev_blk_size(sd->sd_busidx, sd->sd_devidx, 61224857Snwhitehorn &sd->sd_blksize); 62224106Snwhitehorn if (err) 63224106Snwhitehorn goto out; 64224106Snwhitehorn 65224857Snwhitehorn err = ps3repo_read_bus_dev_nblocks(sd->sd_busidx, sd->sd_devidx, 66224857Snwhitehorn &sd->sd_nblocks); 67224106Snwhitehorn if (err) 68224106Snwhitehorn goto out; 69224106Snwhitehorn 70224857Snwhitehorn err = ps3repo_read_bus_dev_nregs(sd->sd_busidx, sd->sd_devidx, 71224857Snwhitehorn &sd->sd_nregs); 72224106Snwhitehorn if (err) 73224106Snwhitehorn goto out; 74224106Snwhitehorn 75224106Snwhitehorn for (i = 0; i < sd->sd_nregs; i++) { 76224857Snwhitehorn err = ps3repo_read_bus_dev_reg_id(sd->sd_busidx, sd->sd_devidx, 77224857Snwhitehorn i, &sd->sd_regs[i].sr_id); 78224106Snwhitehorn if (err) 79224106Snwhitehorn goto out; 80224106Snwhitehorn 81224857Snwhitehorn err = ps3repo_read_bus_dev_reg_start(sd->sd_busidx, 82224857Snwhitehorn sd->sd_devidx, i, &sd->sd_regs[i].sr_start); 83224106Snwhitehorn if (err) 84224106Snwhitehorn goto out; 85224106Snwhitehorn 86224857Snwhitehorn err = ps3repo_read_bus_dev_reg_size(sd->sd_busidx, 87224857Snwhitehorn sd->sd_devidx, i, &sd->sd_regs[i].sr_size); 88224106Snwhitehorn if (err) 89224106Snwhitehorn goto out; 90224106Snwhitehorn } 91224106Snwhitehorn 92224106Snwhitehorn if (!sd->sd_nregs) { 93224106Snwhitehorn err = ENODEV; 94224106Snwhitehorn goto out; 95224106Snwhitehorn } 96224106Snwhitehorn 97224106Snwhitehorn err = lv1_open_device(sd->sd_busid, sd->sd_devid, 0); 98224106Snwhitehorn if (err) 99224106Snwhitehorn goto out; 100224106Snwhitehorn 101224106Snwhitehorn err = lv1_setup_dma(sd->sd_busid, sd->sd_devid, &sd->sd_dmabase); 102224106Snwhitehorn if (err) 103224106Snwhitehorn goto close_dev; 104224106Snwhitehorn 105224106Snwhitehorn return 0; 106224106Snwhitehorn 107224106Snwhitehornclose_dev: 108224106Snwhitehorn 109224106Snwhitehorn lv1_close_device(sd->sd_busid, sd->sd_devid); 110224106Snwhitehorn 111224106Snwhitehornout: 112224106Snwhitehorn 113224106Snwhitehorn return err; 114224106Snwhitehorn} 115224106Snwhitehorn 116224857Snwhitehornstatic char dma_buf[2048] __aligned(2048); 117224857Snwhitehorn 118224106Snwhitehornint ps3stor_read_sectors(struct ps3_stordev *sd, int regidx, 119224106Snwhitehorn uint64_t start_sector, uint64_t sector_count, uint64_t flags, char *buf) 120224106Snwhitehorn{ 121224106Snwhitehorn#define MIN(a, b) ((a) <= (b) ? (a) : (b)) 122224857Snwhitehorn#define BOUNCE_SECTORS (sizeof(dma_buf) / sd->sd_blksize) 123224106Snwhitehorn#define ASYNC_STATUS_POLL_PERIOD 100 /* microseconds */ 124224106Snwhitehorn 125224106Snwhitehorn struct ps3_storreg *reg = &sd->sd_regs[regidx]; 126224106Snwhitehorn uint64_t nleft, nread, nsectors; 127224106Snwhitehorn uint64_t tag, status; 128224106Snwhitehorn unsigned int timeout; 129224857Snwhitehorn int err = 0; 130224106Snwhitehorn 131224106Snwhitehorn nleft = sector_count; 132224106Snwhitehorn nread = 0; 133224106Snwhitehorn 134224106Snwhitehorn while (nleft) { 135224106Snwhitehorn nsectors = MIN(nleft, BOUNCE_SECTORS); 136224106Snwhitehorn 137224857Snwhitehorn err = lv1_storage_read(sd->sd_devid, reg->sr_id, 138224857Snwhitehorn start_sector + nread, nsectors, flags, (uint32_t)dma_buf, 139224857Snwhitehorn &tag); 140224106Snwhitehorn if (err) 141224106Snwhitehorn return err; 142224106Snwhitehorn 143224106Snwhitehorn timeout = 5000000; /* microseconds */ 144224106Snwhitehorn 145224106Snwhitehorn while (1) { 146224106Snwhitehorn if (timeout < ASYNC_STATUS_POLL_PERIOD) 147224106Snwhitehorn return ETIMEDOUT; 148224106Snwhitehorn 149224857Snwhitehorn err = lv1_storage_check_async_status(sd->sd_devid, tag, 150224857Snwhitehorn &status); 151224106Snwhitehorn if (!err && !status) 152224106Snwhitehorn break; 153224106Snwhitehorn 154224106Snwhitehorn delay(ASYNC_STATUS_POLL_PERIOD); 155224106Snwhitehorn timeout -= ASYNC_STATUS_POLL_PERIOD; 156224106Snwhitehorn } 157224106Snwhitehorn 158224857Snwhitehorn if (status != 0) 159224857Snwhitehorn return EIO; 160224857Snwhitehorn 161224857Snwhitehorn memcpy(buf + nread * sd->sd_blksize, (u_char *)dma_buf, 162224857Snwhitehorn nsectors * sd->sd_blksize); 163224106Snwhitehorn nread += nsectors; 164224106Snwhitehorn nleft -= nsectors; 165224106Snwhitehorn } 166224106Snwhitehorn 167224857Snwhitehorn return err; 168224106Snwhitehorn 169224106Snwhitehorn#undef MIN 170224106Snwhitehorn#undef BOUNCE_SECTORS 171224106Snwhitehorn#undef ASYNC_STATUS_POLL_PERIOD 172224106Snwhitehorn} 173224106Snwhitehorn 174224106Snwhitehornvoid ps3stor_print(struct ps3_stordev *sd) 175224106Snwhitehorn{ 176224106Snwhitehorn} 177