Landfall

Annotated pkg/landfall-examples/msc_block_server/msc_block_server.cc

273:8f6ff113d000
8 months ago Paul Boddie Removed debugging output. cpm-library-improvements
paul@272 1
/*
paul@272 2
 * A dataspace server exposing regions of a MMC/SD card.
paul@272 3
 *
paul@272 4
 * Copyright (C) 2020, 2021, 2023, 2024 Paul Boddie <paul@boddie.org.uk>
paul@272 5
 *
paul@272 6
 * This program is free software; you can redistribute it and/or
paul@272 7
 * modify it under the terms of the GNU General Public License as
paul@272 8
 * published by the Free Software Foundation; either version 2 of
paul@272 9
 * the License, or (at your option) any later version.
paul@272 10
 *
paul@272 11
 * This program is distributed in the hope that it will be useful,
paul@272 12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@272 13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
paul@272 14
 * GNU General Public License for more details.
paul@272 15
 *
paul@272 16
 * You should have received a copy of the GNU General Public License
paul@272 17
 * along with this program; if not, write to the Free Software
paul@272 18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
paul@272 19
 * Boston, MA  02110-1301, USA
paul@272 20
 */
paul@272 21
paul@272 22
#include <l4/devices/cpm-x1600.h>
paul@272 23
#include <l4/devices/dma.h>
paul@272 24
#include <l4/devices/dma-x1600.h>
paul@272 25
#include <l4/devices/memory.h>
paul@272 26
#include <l4/devices/msc-x1600.h>
paul@272 27
paul@272 28
#include <l4/re/c/util/cap_alloc.h>
paul@272 29
#include <l4/sys/debugger.h>
paul@272 30
#include <l4/sys/err.h>
paul@272 31
#include <l4/sys/factory.h>
paul@272 32
#include <l4/sys/icu.h>
paul@272 33
#include <l4/sys/ipc.h>
paul@272 34
#include <l4/sys/irq.h>
paul@272 35
paul@272 36
#include <ipc/thread.h>
paul@272 37
paul@272 38
#include <stdio.h>
paul@272 39
#include <stdlib.h>
paul@272 40
paul@272 41
#include <mem/memory_incremental.h>
paul@272 42
#include <fsserver/page_queue_shared.h>
paul@272 43
#include <fsserver/pages.h>
paul@272 44
#include <resource/resource_server.h>
paul@272 45
#include <systypes/env.h>
paul@272 46
paul@272 47
#include "msc_region_opener.h"
paul@272 48
#include "msc_region_operations.h"
paul@272 49
paul@272 50
paul@272 51
paul@272 52
/* Common configuration. */
paul@272 53
paul@272 54
static l4_cap_idx_t icucap;
paul@272 55
paul@272 56
paul@272 57
paul@272 58
/* Device and resource discovery. */
paul@272 59
paul@272 60
static long item_in_range(long start, long end, long index)
paul@272 61
{
paul@272 62
  if (start < end)
paul@272 63
    return start + index;
paul@272 64
  else if (start > end)
paul@272 65
    return start - index;
paul@272 66
  else
paul@272 67
    return start;
paul@272 68
}
paul@272 69
paul@272 70
paul@272 71
paul@272 72
/* Common functions. */
paul@272 73
paul@272 74
static int init_irq(int num, l4_cap_idx_t irq, l4_uint32_t start, l4_uint32_t end)
paul@272 75
{
paul@272 76
  /* Create interrupt object. */
paul@272 77
paul@272 78
  long err = l4_error(l4_factory_create_irq(l4re_global_env->factory, irq));
paul@272 79
paul@272 80
  if (err)
paul@272 81
  {
paul@272 82
    printf("Could not create IRQ object: %ld\n", err);
paul@272 83
    return 1;
paul@272 84
  }
paul@272 85
paul@272 86
  /* Bind interrupt objects to IRQ numbers. */
paul@272 87
paul@272 88
  err = l4_error(l4_icu_bind(icucap,
paul@272 89
                             item_in_range(start, end, num),
paul@272 90
                             irq));
paul@272 91
paul@272 92
  if (err)
paul@272 93
  {
paul@272 94
    printf("Could not bind IRQ to the ICU: %ld\n", err);
paul@272 95
    return 1;
paul@272 96
  }
paul@272 97
paul@272 98
  return 0;
paul@272 99
}
paul@272 100
paul@272 101
paul@272 102
paul@272 103
/* Peripheral resources. */
paul@272 104
paul@272 105
static Cpm_x1600_chip *cpm;
paul@272 106
static Dma_x1600_chip *dma;
paul@272 107
static Msc_x1600_chip *msc;
paul@272 108
paul@272 109
/* Obtain an abstraction for the memory card. */
paul@272 110
paul@272 111
static MscRegionOperations *get_msc_region_operations(int msc_channel_num,
paul@272 112
                                                      int dma_channel_num,
paul@272 113
                                                      int card)
paul@272 114
{
paul@272 115
  l4_addr_t cpm_base = 0, cpm_base_end = 0;
paul@272 116
  l4_addr_t dma_base = 0, dma_base_end = 0;
paul@272 117
  l4_addr_t msc_base = 0, msc_base_end = 0;
paul@272 118
  l4_addr_t msc_phys_base = 0, msc_phys_base_end = 0;
paul@272 119
  l4_uint32_t dma_irq_start = 0, dma_irq_end = 0;
paul@272 120
  l4_uint32_t msc_irq_start = 0, msc_irq_end = 0;
paul@272 121
paul@272 122
  icucap = l4re_env_get_cap("icu");
paul@272 123
paul@272 124
  /* Obtain resource details describing I/O memory. */
paul@272 125
paul@272 126
  if (get_memory("x1600-cpm", &cpm_base, &cpm_base_end) < 0)
paul@272 127
    return NULL;
paul@272 128
paul@272 129
  cpm = new Cpm_x1600_chip(cpm_base);
paul@272 130
paul@272 131
  if (get_memory("x1600-dma", &dma_base, &dma_base_end) < 0)
paul@272 132
    return NULL;
paul@272 133
paul@272 134
  dma = new Dma_x1600_chip(dma_base, dma_base_end, cpm);
paul@272 135
paul@272 136
  if (get_irq("x1600-dma", &dma_irq_start, &dma_irq_end) < 0)
paul@272 137
    return NULL;
paul@272 138
paul@272 139
  l4_cap_idx_t dma_irq = l4re_util_cap_alloc();
paul@272 140
paul@272 141
  if (init_irq(0, dma_irq, dma_irq_start, dma_irq_end))
paul@272 142
    return NULL;
paul@272 143
paul@272 144
  dma->enable();
paul@272 145
paul@272 146
  if (get_memory_complete("x1600-msc", &msc_base, &msc_base_end,
paul@272 147
                          &msc_phys_base, &msc_phys_base_end) < 0)
paul@272 148
    return NULL;
paul@272 149
paul@272 150
  msc = new Msc_x1600_chip(msc_phys_base, msc_base, msc_base_end, cpm);
paul@272 151
paul@272 152
  if (get_irq("x1600-msc", &msc_irq_start, &msc_irq_end) < 0)
paul@272 153
    return NULL;
paul@272 154
paul@272 155
  l4_cap_idx_t msc_irq = l4re_util_cap_alloc();
paul@272 156
paul@272 157
  if (init_irq(msc_channel_num, msc_irq, msc_irq_start, msc_irq_end))
paul@272 158
    return NULL;
paul@272 159
paul@272 160
  Dma_x1600_channel *dma_channel = dma->get_channel(dma_channel_num, dma_irq);
paul@272 161
  Msc_channel *msc_channel = msc->get_channel(msc_channel_num, msc_irq, dma_channel);
paul@272 162
paul@272 163
  msc_channel->enable();
paul@272 164
paul@272 165
  if (card >= msc_channel->num_cards())
paul@272 166
    return NULL;
paul@272 167
paul@272 168
  struct dma_region region;
paul@272 169
paul@272 170
  if (get_dma_region(512, 12, &region))
paul@272 171
    return NULL;
paul@272 172
paul@272 173
  return new MscRegionOperations(msc_channel, card, region);
paul@272 174
}
paul@272 175
paul@272 176
paul@272 177
paul@272 178
/* Default number of pages for files. */
paul@272 179
paul@272 180
const unsigned int MEMORY_PAGES = 20;
paul@272 181
paul@272 182
paul@272 183
paul@272 184
/* Server program. */
paul@272 185
paul@272 186
int main(int argc, char *argv[])
paul@272 187
{
paul@272 188
  l4_debugger_set_object_name(l4re_env()->main_thread, "block_server");
paul@272 189
  long err;
paul@272 190
paul@272 191
  /* Introduce concurrency control. */
paul@272 192
paul@272 193
  err = ipc_thread_init();
paul@272 194
paul@272 195
  if (err)
paul@272 196
  {
paul@272 197
    printf("Initialisation error: %s\n", l4sys_errtostr(err));
paul@272 198
    return 1;
paul@272 199
  }
paul@272 200
paul@272 201
  if (argc < 4)
paul@272 202
  {
paul@272 203
    printf("Need a MSC channel/peripheral number, a DMA channel number, " \
paul@272 204
           "and a card number.\n\n" \
paul@272 205
           "A number of memory pages can be indicated for the use of the " \
paul@272 206
           "server.\n\n" \
paul@272 207
           "A named capability from the environment can be specified.\n");
paul@272 208
    return 1;
paul@272 209
  }
paul@272 210
paul@272 211
  int msc_channel_num = atoi(argv[1]);
paul@272 212
  int dma_channel_num = atoi(argv[2]);
paul@272 213
  int card = atoi(argv[3]);
paul@272 214
paul@272 215
  unsigned int memory_pages = MEMORY_PAGES;
paul@272 216
paul@272 217
  if (argc > 4)
paul@272 218
    memory_pages = atoi(argv[4]);
paul@272 219
paul@272 220
  const char *server_name = (argc > 5) ? argv[5] : ENV_FILESYSTEM_SERVER_NAME;
paul@272 221
paul@272 222
  /* Obtain a DMA space for associating allocated memory with physical
paul@272 223
     addresses. */
paul@272 224
paul@272 225
  l4_cap_idx_t dma_space;
paul@272 226
paul@272 227
  err = get_dma_space(&dma_space);
paul@272 228
paul@272 229
  if (err)
paul@272 230
  {
paul@272 231
    printf("Could not obtain DMA space: %s\n", l4sys_errtostr(err));
paul@272 232
    return 1;
paul@272 233
  }
paul@272 234
paul@272 235
  MscRegionOperations *ops = get_msc_region_operations(msc_channel_num,
paul@272 236
                                                       dma_channel_num,
paul@272 237
                                                       card);
paul@272 238
paul@272 239
  if (ops == NULL)
paul@272 240
  {
paul@272 241
    printf("Could not access memory card peripheral.\n");
paul@272 242
    return 1;
paul@272 243
  }
paul@272 244
paul@272 245
  /* Some memory plus infrastructure. */
paul@272 246
paul@272 247
  MemoryIncremental mem(memory_pages, PAGE_SIZE, dma_space);
paul@272 248
  PageQueueShared queue;
paul@272 249
  Pages pages(&mem, &queue);
paul@272 250
  ResourceRegistry registry(&pages);
paul@272 251
  MscRegionOpener opener(&registry, ops);
paul@272 252
paul@272 253
  /* Register a server associating it with the given object. */
paul@272 254
paul@272 255
  ResourceServer server(&opener);
paul@272 256
  server.bind(server_name);
paul@272 257
paul@272 258
  printf("Starting server using %d pages...\n", memory_pages);
paul@272 259
  server.start();
paul@272 260
paul@272 261
  return 0;
paul@272 262
}
paul@272 263
paul@272 264
// vim: tabstop=2 expandtab shiftwidth=2