2 * Copyright (C) 2011, 2012 glevand <geoffrey.levand@mail.ru>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
33 #include <sys/module.h>
34 #include <sys/kernel.h>
35 #include <sys/systm.h>
38 #include <sys/malloc.h>
40 #include <sys/mutex.h>
42 #include <sys/resource.h>
48 #include <machine/bus.h>
49 #include <machine/platform.h>
50 #include <machine/pmap.h>
51 #include <machine/resource.h>
53 #include "ps3vuart_bus.h"
54 #include "ps3vuart_port.h"
55 #include "ps3av_msg.h"
58 #define PS3AV_LOCK_INIT(_sc) \
59 mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
61 #define PS3AV_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx)
62 #define PS3AV_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
63 #define PS3AV_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
64 #define PS3AV_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
65 #define PS3AV_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->sc_mtx, MA_NOTOWNED)
73 struct resource
*sc_irq
;
76 struct ps3vuart_port sc_port
;
81 static void ps3av_intr(void *arg
);
82 static int ps3av_init(struct ps3av_softc
*sc
);
83 static int ps3av_fini(struct ps3av_softc
*sc
);
85 static int ps3av_dev_open(struct cdev
*dev
, int flags
, int mode
,
87 static int ps3av_dev_close(struct cdev
*dev
, int flags
, int mode
,
89 static int ps3av_dev_read(struct cdev
*dev
, struct uio
*uio
, int ioflag
);
90 static int ps3av_dev_write(struct cdev
*dev
, struct uio
*uio
, int ioflag
);
91 static int ps3av_dev_poll(struct cdev
*dev
, int events
, struct thread
*td
);
93 static MALLOC_DEFINE(M_PS3AV
, "ps3av", "PS3 AV");
95 static struct cdevsw ps3av_cdevsw
= {
96 .d_version
= D_VERSION
,
97 .d_open
= ps3av_dev_open
,
98 .d_close
= ps3av_dev_close
,
99 .d_read
= ps3av_dev_read
,
100 .d_write
= ps3av_dev_write
,
101 .d_poll
= ps3av_dev_poll
,
105 static device_t ps3av_dev
= NULL
;
108 ps3av_probe(device_t dev
)
110 if (ps3vuart_bus_get_type(dev
) != PS3VUART_BUS_TYPE_AV
)
113 device_set_desc(dev
, "Playstation 3 AV");
115 return (BUS_PROBE_SPECIFIC
);
119 ps3av_attach(device_t dev
)
121 struct ps3av_softc
*sc
= device_get_softc(dev
);
133 sc
->sc_irq
= bus_alloc_resource_any(dev
, SYS_RES_IRQ
,
134 &sc
->sc_irq_id
, RF_ACTIVE
);
136 device_printf(dev
, "Could not allocate IRQ\n");
141 err
= bus_setup_intr(dev
, sc
->sc_irq
,
142 INTR_TYPE_MISC
| INTR_MPSAFE
,
143 NULL
, ps3av_intr
, sc
, &sc
->sc_irq_ctx
);
145 device_printf(dev
, "Could not setup IRQ (%d)\n", err
);
149 /* Setup VUART port */
151 err
= ps3vuart_port_init(&sc
->sc_port
, ps3vuart_bus_get_port(dev
));
153 device_printf(dev
, "Could not setup VUART port (%d)\n", err
);
159 err
= ps3av_init(sc
);
161 device_printf(dev
, "Could not setup AV (%d)\n", err
);
162 goto fini_vuart_port
;
165 /* Create char device */
167 sc
->sc_cdev
= make_dev(&ps3av_cdevsw
, 0, UID_ROOT
, GID_WHEEL
, 0600,
170 device_printf(dev
, "Could not create char device\n");
175 sc
->sc_cdev
->si_drv1
= sc
;
189 ps3vuart_port_fini(&sc
->sc_port
);
193 bus_teardown_intr(dev
, sc
->sc_irq
, sc
->sc_irq_ctx
);
197 bus_release_resource(dev
, SYS_RES_IRQ
, sc
->sc_irq_id
, sc
->sc_irq
);
203 PS3AV_LOCK_DESTROY(sc
);
209 ps3av_detach(device_t dev
)
211 struct ps3av_softc
*sc
= device_get_softc(dev
);
217 /* Destroy char device */
219 destroy_dev(sc
->sc_cdev
);
227 bus_teardown_intr(dev
, sc
->sc_irq
, sc
->sc_irq_ctx
);
228 bus_release_resource(dev
, SYS_RES_IRQ
, sc
->sc_irq_id
, sc
->sc_irq
);
230 /* Destroy VUART port */
232 ps3vuart_port_fini(&sc
->sc_port
);
236 PS3AV_LOCK_DESTROY(sc
);
242 ps3av_intr(void *arg
)
244 struct ps3av_softc
*sc
= arg
;
248 ps3vuart_port_intr(&sc
->sc_port
);
254 ps3av_init(struct ps3av_softc
*sc
)
256 PS3AV_ASSERT_LOCKED(sc
);
262 ps3av_fini(struct ps3av_softc
*sc
)
264 PS3AV_ASSERT_LOCKED(sc
);
270 ps3av_set_video_mode(int mode
)
272 struct ps3av_softc
*sc
;
277 sc
= device_get_softc(ps3av_dev
);
287 ps3av_dev_open(struct cdev
*dev
, int flags
, int mode
,
290 struct ps3av_softc
*sc
= dev
->si_drv1
;
300 ps3av_dev_close(struct cdev
*dev
, int flags
, int mode
,
303 struct ps3av_softc
*sc
= dev
->si_drv1
;
313 ps3av_dev_read(struct cdev
*dev
, struct uio
*uio
, int ioflag
)
317 struct ps3av_softc
*sc
= dev
->si_drv1
;
327 buf
= malloc(BUFSZ
, M_PS3AV
, M_WAITOK
);
333 while (uio
->uio_resid
) {
334 err
= ps3vuart_port_read(&sc
->sc_port
, buf
,
335 min(uio
->uio_resid
, BUFSZ
), &read
);
339 err
= uiomove(buf
, read
, uio
);
356 ps3av_dev_write(struct cdev
*dev
, struct uio
*uio
, int ioflag
)
360 struct ps3av_softc
*sc
= dev
->si_drv1
;
370 buf
= malloc(BUFSZ
, M_PS3AV
, M_WAITOK
);
376 while (uio
->uio_resid
) {
377 bytes
= min(uio
->uio_resid
, BUFSZ
);
379 err
= uiomove(buf
, bytes
, uio
);
383 err
= ps3vuart_port_write(&sc
->sc_port
, buf
, bytes
, &written
);
400 ps3av_dev_poll(struct cdev
*dev
, int events
, struct thread
*td
)
402 struct ps3av_softc
*sc
= dev
->si_drv1
;
413 static device_method_t ps3av_methods
[] = {
414 /* Device interface */
415 DEVMETHOD(device_probe
, ps3av_probe
),
416 DEVMETHOD(device_attach
, ps3av_attach
),
417 DEVMETHOD(device_detach
, ps3av_detach
),
422 static driver_t ps3av_driver
= {
425 sizeof(struct ps3av_softc
)
428 static devclass_t ps3av_devclass
;
430 DRIVER_MODULE(ps3av
, ps3vuart_bus
, ps3av_driver
, ps3av_devclass
, 0, 0);
431 MODULE_DEPEND(ps3av
, ps3vuart_port
, 1, 1, 1);
432 MODULE_VERSION(ps3av
, 1);