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