#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/interrupt.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/rman.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/timetc.h>
#include <machine/bus.h>
#include <machine/intr.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <arm/ti/ti_cpuid.h>
#include <arm/ti/ti_sysc.h>
#include <arm/ti/ti_sdma.h>
#include <arm/ti/ti_sdmareg.h>
struct ti_sdma_channel {
uint32_t reg_csdp;
uint32_t reg_ccr;
uint32_t reg_cicr;
uint32_t need_reg_write;
void (*callback)(unsigned int ch, uint32_t ch_status, void *data);
void* callback_data;
};
struct ti_sdma_softc {
device_t sc_dev;
struct resource* sc_irq_res;
struct resource* sc_mem_res;
struct mtx sc_mtx;
uint32_t sc_hw_rev;
uint32_t sc_active_channels;
struct ti_sdma_channel sc_channel[NUM_DMA_CHANNELS];
};
static struct ti_sdma_softc *ti_sdma_sc = NULL;
#define TI_SDMA_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx)
#define TI_SDMA_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->sc_mtx)
#define TI_SDMA_LOCK_INIT(_sc) \
mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
"ti_sdma", MTX_SPIN)
#define TI_SDMA_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
#define TI_SDMA_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
#define TI_SDMA_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
static void ti_sdma_intr(void *);
static inline uint32_t
ti_sdma_read_4(struct ti_sdma_softc *sc, bus_size_t off)
{
return bus_read_4(sc->sc_mem_res, off);
}
static inline void
ti_sdma_write_4(struct ti_sdma_softc *sc, bus_size_t off, uint32_t val)
{
bus_write_4(sc->sc_mem_res, off, val);
}
static inline int
ti_sdma_is_omap3_rev(struct ti_sdma_softc *sc)
{
return (sc->sc_hw_rev == DMA4_OMAP3_REV);
}
static inline int
ti_sdma_is_omap4_rev(struct ti_sdma_softc *sc)
{
return (sc->sc_hw_rev == DMA4_OMAP4_REV);
}
static void
ti_sdma_intr(void *arg)
{
struct ti_sdma_softc *sc = ti_sdma_sc;
uint32_t intr;
uint32_t csr;
unsigned int ch, j;
struct ti_sdma_channel* channel;
TI_SDMA_LOCK(sc);
for (j = 0; j < NUM_DMA_IRQS; j++) {
intr = ti_sdma_read_4(sc, DMA4_IRQSTATUS_L(j));
intr &= ti_sdma_read_4(sc, DMA4_IRQENABLE_L(j));
if (intr == 0x00000000)
continue;
for (ch = 0; ch < NUM_DMA_CHANNELS; ch++) {
if (intr & (1 << ch)) {
channel = &sc->sc_channel[ch];
csr = ti_sdma_read_4(sc, DMA4_CSR(ch));
if (csr == 0) {
device_printf(sc->sc_dev, "Spurious DMA IRQ for channel "
"%d\n", ch);
continue;
}
if ((sc->sc_active_channels & (1 << ch)) == 0) {
device_printf(sc->sc_dev, "IRQ %d for a non-activated "
"channel %d\n", j, ch);
continue;
}
if (csr & DMA4_CSR_DROP)
device_printf(sc->sc_dev, "Synchronization event drop "
"occurred during the transfer on channel %u\n",
ch);
if (csr & DMA4_CSR_SECURE_ERR)
device_printf(sc->sc_dev, "Secure transaction error event "
"on channel %u\n", ch);
if (csr & DMA4_CSR_MISALIGNED_ADRS_ERR)
device_printf(sc->sc_dev, "Misaligned address error event "
"on channel %u\n", ch);
if (csr & DMA4_CSR_TRANS_ERR) {
device_printf(sc->sc_dev, "Transaction error event on "
"channel %u\n", ch);
}
ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK);
ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch));
if (channel->callback)
channel->callback(ch, csr, channel->callback_data);
}
}
}
TI_SDMA_UNLOCK(sc);
return;
}
int
ti_sdma_activate_channel(unsigned int *ch,
void (*callback)(unsigned int ch, uint32_t status, void *data),
void *data)
{
struct ti_sdma_softc *sc = ti_sdma_sc;
struct ti_sdma_channel *channel = NULL;
uint32_t addr;
unsigned int i;
if (sc == NULL)
return (ENOMEM);
if (ch == NULL)
return (EINVAL);
TI_SDMA_LOCK(sc);
if (sc->sc_active_channels == 0xffffffff) {
TI_SDMA_UNLOCK(sc);
return (ENOMEM);
}
for (i = 0; i < NUM_DMA_CHANNELS; i++) {
if (!(sc->sc_active_channels & (0x1 << i))) {
sc->sc_active_channels |= (0x1 << i);
*ch = i;
break;
}
}
channel = &sc->sc_channel[*ch];
channel->callback = callback;
channel->callback_data = data;
channel->need_reg_write = 1;
channel->reg_csdp = DMA4_CSDP_DATA_TYPE(0x2)
| DMA4_CSDP_SRC_BURST_MODE(0)
| DMA4_CSDP_DST_BURST_MODE(0)
| DMA4_CSDP_SRC_ENDIANISM(0)
| DMA4_CSDP_DST_ENDIANISM(0)
| DMA4_CSDP_WRITE_MODE(0)
| DMA4_CSDP_SRC_PACKED(0)
| DMA4_CSDP_DST_PACKED(0);
channel->reg_ccr = DMA4_CCR_DST_ADDRESS_MODE(1)
| DMA4_CCR_SRC_ADDRESS_MODE(1)
| DMA4_CCR_READ_PRIORITY(0)
| DMA4_CCR_WRITE_PRIORITY(0)
| DMA4_CCR_SYNC_TRIGGER(0)
| DMA4_CCR_FRAME_SYNC(0)
| DMA4_CCR_BLOCK_SYNC(0);
channel->reg_cicr = DMA4_CICR_TRANS_ERR_IE
| DMA4_CICR_SECURE_ERR_IE
| DMA4_CICR_SUPERVISOR_ERR_IE
| DMA4_CICR_MISALIGNED_ADRS_ERR_IE;
for (addr = DMA4_CCR(*ch); addr <= DMA4_COLOR(*ch); addr += 4)
ti_sdma_write_4(sc, addr, 0x00000000);
TI_SDMA_UNLOCK(sc);
return 0;
}
int
ti_sdma_deactivate_channel(unsigned int ch)
{
struct ti_sdma_softc *sc = ti_sdma_sc;
unsigned int j;
unsigned int addr;
if (sc == NULL)
return (ENOMEM);
TI_SDMA_LOCK(sc);
if ((sc->sc_active_channels & (1 << ch)) == 0) {
TI_SDMA_UNLOCK(sc);
return (EBUSY);
}
sc->sc_active_channels &= ~(1 << ch);
ti_sdma_write_4(sc, DMA4_CICR(ch), 0);
ti_sdma_write_4(sc, DMA4_CCR(ch), 0);
ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK);
for (j = 0; j < NUM_DMA_IRQS; j++) {
ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch));
}
for (addr = DMA4_CCR(ch); addr <= DMA4_COLOR(ch); addr += 4)
ti_sdma_write_4(sc, addr, 0x00000000);
TI_SDMA_UNLOCK(sc);
return 0;
}
int
ti_sdma_disable_channel_irq(unsigned int ch)
{
struct ti_sdma_softc *sc = ti_sdma_sc;
uint32_t irq_enable;
unsigned int j;
if (sc == NULL)
return (ENOMEM);
TI_SDMA_LOCK(sc);
if ((sc->sc_active_channels & (1 << ch)) == 0) {
TI_SDMA_UNLOCK(sc);
return (EINVAL);
}
sc->sc_channel[ch].reg_cicr = 0x0000;
ti_sdma_write_4(sc, DMA4_CICR(ch), 0x0000);
for (j = 0; j < NUM_DMA_IRQS; j++) {
irq_enable = ti_sdma_read_4(sc, DMA4_IRQENABLE_L(j));
irq_enable &= ~(1 << ch);
ti_sdma_write_4(sc, DMA4_IRQENABLE_L(j), irq_enable);
}
sc->sc_channel[ch].need_reg_write = 1;
TI_SDMA_UNLOCK(sc);
return (0);
}
int
ti_sdma_enable_channel_irq(unsigned int ch, uint32_t flags)
{
struct ti_sdma_softc *sc = ti_sdma_sc;
uint32_t irq_enable;
if (sc == NULL)
return (ENOMEM);
TI_SDMA_LOCK(sc);
if ((sc->sc_active_channels & (1 << ch)) == 0) {
TI_SDMA_UNLOCK(sc);
return (EINVAL);
}
flags |= DMA4_CICR_TRANS_ERR_IE | DMA4_CICR_SECURE_ERR_IE |
DMA4_CICR_SUPERVISOR_ERR_IE | DMA4_CICR_MISALIGNED_ADRS_ERR_IE;
sc->sc_channel[ch].reg_cicr = flags;
ti_sdma_write_4(sc, DMA4_CICR(ch), flags);
irq_enable = ti_sdma_read_4(sc, DMA4_IRQENABLE_L(0));
irq_enable |= (1 << ch);
ti_sdma_write_4(sc, DMA4_IRQENABLE_L(0), irq_enable);
sc->sc_channel[ch].need_reg_write = 1;
TI_SDMA_UNLOCK(sc);
return (0);
}
int
ti_sdma_get_channel_status(unsigned int ch, uint32_t *status)
{
struct ti_sdma_softc *sc = ti_sdma_sc;
uint32_t csr;
if (sc == NULL)
return (ENOMEM);
TI_SDMA_LOCK(sc);
if ((sc->sc_active_channels & (1 << ch)) == 0) {
TI_SDMA_UNLOCK(sc);
return (EINVAL);
}
TI_SDMA_UNLOCK(sc);
csr = ti_sdma_read_4(sc, DMA4_CSR(ch));
if (status != NULL)
*status = csr;
return (0);
}
int
ti_sdma_start_xfer(unsigned int ch, unsigned int src_paddr,
unsigned long dst_paddr,
unsigned int frmcnt, unsigned int elmcnt)
{
struct ti_sdma_softc *sc = ti_sdma_sc;
struct ti_sdma_channel *channel;
uint32_t ccr;
if (sc == NULL)
return (ENOMEM);
TI_SDMA_LOCK(sc);
if ((sc->sc_active_channels & (1 << ch)) == 0) {
TI_SDMA_UNLOCK(sc);
return (EINVAL);
}
channel = &sc->sc_channel[ch];
ti_sdma_write_4(sc, DMA4_CSDP(ch),
channel->reg_csdp | DMA4_CSDP_WRITE_MODE(1));
ti_sdma_write_4(sc, DMA4_CEN(ch), elmcnt);
ti_sdma_write_4(sc, DMA4_CFN(ch), frmcnt);
ti_sdma_write_4(sc, DMA4_CSSA(ch), src_paddr);
ti_sdma_write_4(sc, DMA4_CDSA(ch), dst_paddr);
ti_sdma_write_4(sc, DMA4_CCR(ch), channel->reg_ccr);
ti_sdma_write_4(sc, DMA4_CSE(ch), 0x0001);
ti_sdma_write_4(sc, DMA4_CSF(ch), 0x0001);
ti_sdma_write_4(sc, DMA4_CDE(ch), 0x0001);
ti_sdma_write_4(sc, DMA4_CDF(ch), 0x0001);
ti_sdma_write_4(sc, DMA4_CSR(ch), 0x1FFE);
ccr = ti_sdma_read_4(sc, DMA4_CCR(ch));
ccr |= (1 << 7);
ti_sdma_write_4(sc, DMA4_CCR(ch), ccr);
channel->need_reg_write = 0;
TI_SDMA_UNLOCK(sc);
return (0);
}
int
ti_sdma_start_xfer_packet(unsigned int ch, unsigned int src_paddr,
unsigned long dst_paddr, unsigned int frmcnt,
unsigned int elmcnt, unsigned int pktsize)
{
struct ti_sdma_softc *sc = ti_sdma_sc;
struct ti_sdma_channel *channel;
uint32_t ccr;
if (sc == NULL)
return (ENOMEM);
TI_SDMA_LOCK(sc);
if ((sc->sc_active_channels & (1 << ch)) == 0) {
TI_SDMA_UNLOCK(sc);
return (EINVAL);
}
channel = &sc->sc_channel[ch];
if (channel->need_reg_write)
ti_sdma_write_4(sc, DMA4_CSDP(ch),
channel->reg_csdp | DMA4_CSDP_WRITE_MODE(1));
ti_sdma_write_4(sc, DMA4_CEN(ch), elmcnt);
ti_sdma_write_4(sc, DMA4_CFN(ch), frmcnt);
ti_sdma_write_4(sc, DMA4_CSSA(ch), src_paddr);
ti_sdma_write_4(sc, DMA4_CDSA(ch), dst_paddr);
ti_sdma_write_4(sc, DMA4_CCR(ch),
channel->reg_ccr | DMA4_CCR_PACKET_TRANS);
ti_sdma_write_4(sc, DMA4_CSE(ch), 0x0001);
if (channel->reg_ccr & DMA4_CCR_SEL_SRC_DST_SYNC(1))
ti_sdma_write_4(sc, DMA4_CSF(ch), pktsize);
else
ti_sdma_write_4(sc, DMA4_CDF(ch), pktsize);
ti_sdma_write_4(sc, DMA4_CDE(ch), 0x0001);
ti_sdma_write_4(sc, DMA4_CSR(ch), 0x1FFE);
ccr = ti_sdma_read_4(sc, DMA4_CCR(ch));
ccr |= (1 << 7);
ti_sdma_write_4(sc, DMA4_CCR(ch), ccr);
channel->need_reg_write = 0;
TI_SDMA_UNLOCK(sc);
return (0);
}
int
ti_sdma_stop_xfer(unsigned int ch)
{
struct ti_sdma_softc *sc = ti_sdma_sc;
unsigned int j;
if (sc == NULL)
return (ENOMEM);
TI_SDMA_LOCK(sc);
if ((sc->sc_active_channels & (1 << ch)) == 0) {
TI_SDMA_UNLOCK(sc);
return (EINVAL);
}
ti_sdma_write_4(sc, DMA4_CICR(ch), 0);
ti_sdma_write_4(sc, DMA4_CCR(ch), 0);
ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK);
for (j = 0; j < NUM_DMA_IRQS; j++) {
ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch));
}
sc->sc_channel[ch].need_reg_write = 1;
TI_SDMA_UNLOCK(sc);
return (0);
}
int
ti_sdma_set_xfer_endianess(unsigned int ch, unsigned int src, unsigned int dst)
{
struct ti_sdma_softc *sc = ti_sdma_sc;
if (sc == NULL)
return (ENOMEM);
TI_SDMA_LOCK(sc);
if ((sc->sc_active_channels & (1 << ch)) == 0) {
TI_SDMA_UNLOCK(sc);
return (EINVAL);
}
sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_SRC_ENDIANISM(1);
sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_SRC_ENDIANISM(src);
sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_DST_ENDIANISM(1);
sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_DST_ENDIANISM(dst);
sc->sc_channel[ch].need_reg_write = 1;
TI_SDMA_UNLOCK(sc);
return 0;
}
int
ti_sdma_set_xfer_burst(unsigned int ch, unsigned int src, unsigned int dst)
{
struct ti_sdma_softc *sc = ti_sdma_sc;
if (sc == NULL)
return (ENOMEM);
TI_SDMA_LOCK(sc);
if ((sc->sc_active_channels & (1 << ch)) == 0) {
TI_SDMA_UNLOCK(sc);
return (EINVAL);
}
sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_SRC_BURST_MODE(0x3);
sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_SRC_BURST_MODE(src);
sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_DST_BURST_MODE(0x3);
sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_DST_BURST_MODE(dst);
sc->sc_channel[ch].need_reg_write = 1;
TI_SDMA_UNLOCK(sc);
return 0;
}
int
ti_sdma_set_xfer_data_type(unsigned int ch, unsigned int type)
{
struct ti_sdma_softc *sc = ti_sdma_sc;
if (sc == NULL)
return (ENOMEM);
TI_SDMA_LOCK(sc);
if ((sc->sc_active_channels & (1 << ch)) == 0) {
TI_SDMA_UNLOCK(sc);
return (EINVAL);
}
sc->sc_channel[ch].reg_csdp &= ~DMA4_CSDP_DATA_TYPE(0x3);
sc->sc_channel[ch].reg_csdp |= DMA4_CSDP_DATA_TYPE(type);
sc->sc_channel[ch].need_reg_write = 1;
TI_SDMA_UNLOCK(sc);
return 0;
}
int
ti_sdma_set_callback(unsigned int ch,
void (*callback)(unsigned int ch, uint32_t status, void *data),
void *data)
{
struct ti_sdma_softc *sc = ti_sdma_sc;
if (sc == NULL)
return (ENOMEM);
TI_SDMA_LOCK(sc);
if ((sc->sc_active_channels & (1 << ch)) == 0) {
TI_SDMA_UNLOCK(sc);
return (EINVAL);
}
sc->sc_channel[ch].callback = callback;
sc->sc_channel[ch].callback_data = data;
sc->sc_channel[ch].need_reg_write = 1;
TI_SDMA_UNLOCK(sc);
return 0;
}
int
ti_sdma_sync_params(unsigned int ch, unsigned int trigger, unsigned int mode)
{
struct ti_sdma_softc *sc = ti_sdma_sc;
uint32_t ccr;
if (sc == NULL)
return (ENOMEM);
TI_SDMA_LOCK(sc);
if ((sc->sc_active_channels & (1 << ch)) == 0) {
TI_SDMA_UNLOCK(sc);
return (EINVAL);
}
ccr = sc->sc_channel[ch].reg_ccr;
ccr &= ~DMA4_CCR_SYNC_TRIGGER(0x7F);
ccr |= DMA4_CCR_SYNC_TRIGGER(trigger + 1);
if (mode & TI_SDMA_SYNC_FRAME)
ccr |= DMA4_CCR_FRAME_SYNC(1);
else
ccr &= ~DMA4_CCR_FRAME_SYNC(1);
if (mode & TI_SDMA_SYNC_BLOCK)
ccr |= DMA4_CCR_BLOCK_SYNC(1);
else
ccr &= ~DMA4_CCR_BLOCK_SYNC(1);
if (mode & TI_SDMA_SYNC_TRIG_ON_SRC)
ccr |= DMA4_CCR_SEL_SRC_DST_SYNC(1);
else
ccr &= ~DMA4_CCR_SEL_SRC_DST_SYNC(1);
sc->sc_channel[ch].reg_ccr = ccr;
sc->sc_channel[ch].need_reg_write = 1;
TI_SDMA_UNLOCK(sc);
return 0;
}
int
ti_sdma_set_addr_mode(unsigned int ch, unsigned int src_mode,
unsigned int dst_mode)
{
struct ti_sdma_softc *sc = ti_sdma_sc;
uint32_t ccr;
if (sc == NULL)
return (ENOMEM);
TI_SDMA_LOCK(sc);
if ((sc->sc_active_channels & (1 << ch)) == 0) {
TI_SDMA_UNLOCK(sc);
return (EINVAL);
}
ccr = sc->sc_channel[ch].reg_ccr;
ccr &= ~DMA4_CCR_SRC_ADDRESS_MODE(0x3);
ccr |= DMA4_CCR_SRC_ADDRESS_MODE(src_mode);
ccr &= ~DMA4_CCR_DST_ADDRESS_MODE(0x3);
ccr |= DMA4_CCR_DST_ADDRESS_MODE(dst_mode);
sc->sc_channel[ch].reg_ccr = ccr;
sc->sc_channel[ch].need_reg_write = 1;
TI_SDMA_UNLOCK(sc);
return 0;
}
static int
ti_sdma_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "ti,omap4430-sdma"))
return (ENXIO);
device_set_desc(dev, "TI sDMA Controller");
return (0);
}
static int
ti_sdma_attach(device_t dev)
{
struct ti_sdma_softc *sc = device_get_softc(dev);
unsigned int timeout;
unsigned int i;
int rid;
void *ihl;
int err;
sc->sc_dev = dev;
sc->sc_active_channels = 0x00000000;
TI_SDMA_LOCK_INIT(sc);
rid = 0;
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
if (sc->sc_mem_res == NULL)
panic("%s: Cannot map registers", device_get_name(dev));
ti_sysc_clock_enable(device_get_parent(dev));
sc->sc_hw_rev = ti_sdma_read_4(sc,
ti_sysc_get_rev_address_offset_host(device_get_parent(dev)));
device_printf(dev, "sDMA revision %08x\n", sc->sc_hw_rev);
if (!ti_sdma_is_omap4_rev(sc) && !ti_sdma_is_omap3_rev(sc)) {
device_printf(sc->sc_dev, "error - unknown sDMA H/W revision\n");
return (EINVAL);
}
for (i = 0; i < NUM_DMA_IRQS; i++) {
ti_sdma_write_4(sc, DMA4_IRQENABLE_L(i), 0x00000000);
}
if (ti_sdma_is_omap3_rev(sc)) {
ti_sdma_write_4(sc, DMA4_OCP_SYSCONFIG, 0x0002);
timeout = (hz < 10) ? 1 : ((100 * hz) / 1000);
while ((ti_sdma_read_4(sc, DMA4_SYSSTATUS) & 0x1) == 0x0) {
pause("DMARESET", 1);
if (timeout-- == 0) {
device_printf(sc->sc_dev, "sDMA reset operation timed out\n");
return (EINVAL);
}
}
}
rid = 0;
sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_ACTIVE | RF_SHAREABLE);
if (sc->sc_irq_res == NULL)
panic("Unable to setup the dma irq handler.\n");
err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
NULL, ti_sdma_intr, NULL, &ihl);
if (err)
panic("%s: Cannot register IRQ", device_get_name(dev));
ti_sdma_sc = sc;
return (0);
}
static device_method_t ti_sdma_methods[] = {
DEVMETHOD(device_probe, ti_sdma_probe),
DEVMETHOD(device_attach, ti_sdma_attach),
{0, 0},
};
static driver_t ti_sdma_driver = {
"ti_sdma",
ti_sdma_methods,
sizeof(struct ti_sdma_softc),
};
DRIVER_MODULE(ti_sdma, simplebus, ti_sdma_driver, 0, 0);
MODULE_DEPEND(ti_sdma, ti_sysc, 1, 1, 1);