144 lines
4.0 KiB
C
144 lines
4.0 KiB
C
/* $NetBSD: sif.c,v 1.13 2023/11/05 21:54:27 andvar Exp $ */
|
|
|
|
/*-
|
|
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This code is derived from software contributed to The NetBSD Foundation
|
|
* by UCHIYAMA Yasushi.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
__KERNEL_RCSID(0, "$NetBSD: sif.c,v 1.13 2023/11/05 21:54:27 andvar Exp $");
|
|
|
|
#include "debug_playstation2.h"
|
|
|
|
#include <sys/intr.h>
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/kernel.h>
|
|
|
|
#include <playstation2/playstation2/sifbios.h>
|
|
#include <playstation2/ee/dmacvar.h>
|
|
#include <playstation2/ee/sifvar.h>
|
|
|
|
#ifdef SIF_DEBUG
|
|
int __spd_total_alloc;
|
|
int sif_debug = 1;
|
|
#define DPRINTF(fmt, args...) \
|
|
if (sif_debug) \
|
|
printf("%s: " fmt, __func__ , ##args)
|
|
#define DPRINTFN(n, arg) \
|
|
if (sif_debug > (n)) \
|
|
n printf("%s: " fmt, __func__ , ##args)
|
|
#else
|
|
#define DPRINTF(arg...) ((void)0)
|
|
#define DPRINTFN(n, arg...) ((void)0)
|
|
#endif
|
|
|
|
#define ROUND64(x) ((((u_int32_t)(x)) + 63) & ~64)
|
|
#define BCD_TO_DECIMAL(x) \
|
|
({ \
|
|
typeof(x) x_ = x; \
|
|
(((x_) >> 4) * 10 + ((x_) & 0xf)); \
|
|
})
|
|
#define MAJOR(x) BCD_TO_DECIMAL(((x) >> 8) & 0xff)
|
|
#define MINOR(x) BCD_TO_DECIMAL((x) & 0xff)
|
|
|
|
void
|
|
sif_init(void)
|
|
{
|
|
u_int32_t vers;
|
|
|
|
vers = sifbios_getver();
|
|
printf("PlayStation 2 SIF BIOS version %d.%d\n",
|
|
MAJOR(vers), MINOR(vers));
|
|
|
|
/* Initialize SIF */
|
|
if (sifdma_init() < 0)
|
|
panic("SIFDMA");
|
|
if (sifcmd_init() < 0)
|
|
panic("SIFCMD");
|
|
dmac_intr_establish(D_CH5_SIF0, IPL_TTY, sifcmd_intr, 0);
|
|
if (sifrpc_init() < 0)
|
|
panic("SIFRPC");
|
|
if (iopmem_init() < 0)
|
|
panic("IOP Memory");
|
|
}
|
|
|
|
void
|
|
sif_exit(void)
|
|
{
|
|
|
|
sifrpc_exit();
|
|
sifcmd_exit();
|
|
dmac_intr_disestablish((void *)D_CH5_SIF0);
|
|
sifdma_exit();
|
|
}
|
|
|
|
int
|
|
iopdma_allocate_buffer(struct iopdma_segment *seg, size_t size)
|
|
{
|
|
/*
|
|
* To avoid cache inconsistecy as the result of DMA(to memory),
|
|
* DMA buffer size is set to multiple of CPU cache line size (64B)
|
|
* and aligned to cache line.
|
|
*/
|
|
seg->size = ROUND64(size);
|
|
|
|
seg->iop_paddr = iopmem_alloc(seg->size);
|
|
|
|
if (seg->iop_paddr == 0) {
|
|
printf("%s: can't allocate IOP memory.\n", __func__);
|
|
DPRINTF("request = %lu byte, current total = %#x\n",
|
|
size, __spd_total_alloc);
|
|
return (1);
|
|
}
|
|
|
|
seg->ee_vaddr = IOPPHYS_TO_EEKV(seg->iop_paddr);
|
|
|
|
#ifdef SIF_DEBUG
|
|
__spd_total_alloc += size;
|
|
#endif
|
|
DPRINTF("0x%08x+%#lx (total=%#x)\n", seg->iop_paddr, size,
|
|
__spd_total_alloc);
|
|
|
|
KDASSERT((seg->ee_vaddr & 63) == 0);
|
|
|
|
return (0);
|
|
}
|
|
|
|
void
|
|
iopdma_free_buffer(struct iopdma_segment *seg)
|
|
{
|
|
int ret __unused;
|
|
|
|
ret = iopmem_free(seg->iop_paddr);
|
|
#ifdef SIF_DEBUG
|
|
__spd_total_alloc -= seg->size;
|
|
#endif
|
|
DPRINTF("0x%08x (total=%#x, result=%d)\n", seg->iop_paddr,
|
|
__spd_total_alloc, ret);
|
|
}
|