module 8.93 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/* Copyright 1998 Acorn Computers Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * Generic (c.module)
 *
 * THIS FILE REQUIRES CUSTOMISATION
 *
 *  Acorn Computers Ltd. 1997
 *
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "kernel.h"
#include "swis.h"
#include "sys/errno.h"
#include "module.h"
Stewart Brodie's avatar
Stewart Brodie committed
30
#include "GenericHdr.h"
31 32 33 34 35 36
#include "utils.h"
#include "protocol.h"
#include "connect.h"

#include "MemCheck:MemCheck.h"

Stewart Brodie's avatar
Stewart Brodie committed
37 38 39 40 41 42
#if CMHG_VERSION < 516
#define CMHG_CONST
#else
#define CMHG_CONST const
#endif

43 44 45 46 47 48 49
/* TinySupport SWIs.  This does not work if any library static data
 * is used within the module.  This means errno (__errno) and __ctype
 * (as used by any macro call to is.... functions)  If you re-enable
 * this SWI call, this module will fail to work at all.
 */
#define NO_TINYSTUBS

Stewart Brodie's avatar
Stewart Brodie committed
50
#ifdef ROM
51
#ifndef NO_TINYSTUBS
Stewart Brodie's avatar
Stewart Brodie committed
52
static _kernel_oserror *__ROM;
Stewart Brodie's avatar
Stewart Brodie committed
53 54
#define TinySupport_Share       (0x82c43)
#define TinySupport_Die         (0x82c41)
55
#endif
Stewart Brodie's avatar
Stewart Brodie committed
56
#endif
57

Stewart Brodie's avatar
Stewart Brodie committed
58
#define NO_SUCH_SWI     (0x1E6)
59 60 61 62

#define URL_PROTOCOL_REGISTER 0x83e20
#define URL_PROTOCOL_DEREGISTER 0x83e21

Stewart Brodie's avatar
Stewart Brodie committed
63 64 65 66 67
#ifndef ROM
extern int messages_file(void);
#endif

#ifndef ROM
68
#ifdef DEFINE_ERRNO
Stewart Brodie's avatar
Stewart Brodie committed
69 70
int __errno;
#endif
71
#endif
Stewart Brodie's avatar
Stewart Brodie committed
72 73


74 75 76 77 78 79
static int callback_pending_flag;

/* Sets clibrary_realloc_routine_is_buggy to 1 if RISC OS 3.1 or earlier (ROM realloc is broken) */
static int clibrary_realloc_routine_is_buggy;
static void module_check_os_version(void)
{
Stewart Brodie's avatar
Stewart Brodie committed
80 81 82
        int os;
        (void) _swix(OS_Byte, _INR(0,2)|_OUT(1), 129, 0, 255, &os);
        clibrary_realloc_routine_is_buggy = (os <= 0xA4);
83 84 85 86 87 88 89
}


static int registered;

static _kernel_oserror *try_to_register(void)
{
Stewart Brodie's avatar
Stewart Brodie committed
90 91 92 93 94 95 96 97 98 99 100
        _kernel_oserror *e;

        if (registered) return NULL;
        e = _swix(URL_PROTOCOL_REGISTER, _INR(0,4), 0,
                GenericFetcher_00,
                CONNECT_DEFAULT_PROTOCOL_NAME ":",
                Module_VersionNumber, Module_Help "  Acorn");
        if (e == NULL) {
                registered = 1;
        }
        return e;
101 102 103 104
}

static _kernel_oserror *try_to_deregister(void)
{
Stewart Brodie's avatar
Stewart Brodie committed
105 106 107 108 109 110 111
        if (!registered) {
                return NULL;
        }
        else {
                registered = 0;
                return _swix(URL_PROTOCOL_DEREGISTER, _INR(0,1), 0, GenericFetcher_00);
        }
112 113 114 115
}

static _kernel_oserror *register_with_url(void)
{
Stewart Brodie's avatar
Stewart Brodie committed
116 117 118 119 120 121 122 123 124 125 126
        _kernel_oserror *e;

        e = try_to_register();
        if (e == NULL) return e;
        if (e->errnum != NO_SUCH_SWI) return e;
        #ifndef ROM
        e = _swix(OS_Module, _INR(0,1), 1 /* Load */, "System:Modules.Network.URL.URL");
        return try_to_register();
        #else
        return NULL;
        #endif
127 128 129 130 131
}

/*************************************************************/
/* _kernel_oserror *module_init(char *cmd_fail, int podu...  */
/*************************************************************/
Stewart Brodie's avatar
Stewart Brodie committed
132
/* Start up and register ourselves with the URL module       */
133
/*************************************************************/
Stewart Brodie's avatar
Stewart Brodie committed
134
_kernel_oserror *module_init(CMHG_CONST char *cmd_tail, int podule_base, void *pw)
135
{
Stewart Brodie's avatar
Stewart Brodie committed
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
        _kernel_oserror *e;

        (void) podule_base;
        (void) cmd_tail;

        #ifdef ROM
        #ifndef NO_TINYSTUBS
        __ROM = _swix(TinySupport_Share, _IN(0), pw);
        #endif
        #endif

        debug_initialise("Generic", 0, 0);
        debug_output_device(DEBUGIT_OUTPUT);

        registered = 0;
        callback_pending_flag = 0;

        session_init();
        module_check_os_version();

        MemCheck_InitNoDebug();
        MemCheck_SetQuitting(0,0);
        MemCheck_RedirectToFilename("adfs::4.Trace.Genericmem");
        MemCheck_InterceptSCLStringFunctions();
        MemCheck_RegisterMiscBlock((void *)0x01c0001c,8164);
        MemCheck_SetStoreMallocFunctions(1);
        MemCheck_SetReportFrees(1);
        MemCheck_SetChecking(0,0);

        e = register_with_url();
        if (e) {
                #ifndef ROM
                if (e->errnum == NO_SUCH_SWI) {
                        _kernel_oserror *newe = find_error();
                        newe->errnum = 0x115; /* NeedMod */
                        strcpy(newe->errmess, "NeedMod");
                        e = _swix(MessageTrans_ErrorLookup, _INR(0,7), newe, 0, 0, 0, Module_Title, "URL", 0, 0);
                }
                #endif
                return e;
        }

        #ifndef ROM
        e = _swix(ResourceFS_RegisterFiles, _IN(0), messages_file());
        if (e) {
                (void) try_to_deregister();
                return e;
        }
        #endif

        if (getenv(Module_Title "$Path")) {
                e = messages_file_open(Module_Title ":Messages");
        }
        else {
                e = messages_file_open("Resources:$.Resources.URL." "Generic" ".Messages");
        }

        if (e) {
                #ifndef ROM
                (void) _swix(ResourceFS_DeregisterFiles, _IN(0), messages_file());
                #endif
                (void) try_to_deregister();
                return e;
        }

        callback_pending_flag = 0;
        /* Set up a callevery */
        e = _swix(OS_CallEvery, _INR(0,2), 15*100-1, callevery_entry, pw);
        if (e) {
                messages_file_close();
                #ifndef ROM
                (void) _swix(ResourceFS_DeregisterFiles, _IN(0), messages_file());
                #endif
                (void) try_to_deregister();
                return e;
        }

        return NULL;
214 215 216 217 218
}


void service_handler(int service_number, _kernel_swi_regs *r, void *pw)
{
Stewart Brodie's avatar
Stewart Brodie committed
219 220 221 222 223 224 225 226 227 228 229 230 231 232
        dprintf(("module_1", "Service &%X: R0 = %d for URL version  %03d\n", service_number, r->r[0], r->r[2]));
        (void) pw;
        (void) service_number;

        switch (r->r[0]) {
                case 0:
                        (void) try_to_register();
                        break;
                case 1:
                        (void) try_to_deregister();
                        break;
                default:
                        break;
        }
233 234 235 236 237
}


_kernel_oserror *module_kill(int fatal, int podule, void *pw)
{
Stewart Brodie's avatar
Stewart Brodie committed
238 239
        (void) fatal;
        (void) podule;
240

Stewart Brodie's avatar
Stewart Brodie committed
241 242 243 244 245 246 247 248
        (void) _swix(OS_RemoveTickerEvent, _INR(0,1), callevery_entry, pw);
        if (callback_pending_flag) {
                (void) _swix(OS_RemoveCallBack, _INR(0,1), callback_entry, pw);
        }
        messages_file_close();
        #ifndef ROM
        (void) _swix(ResourceFS_DeregisterFiles, _IN(0), messages_file());
        #endif
249

Stewart Brodie's avatar
Stewart Brodie committed
250
        ses_kill_all();
251 252 253

       (void) try_to_deregister();

254 255
        #ifdef ROM
        #ifndef NO_TINYSTUBS
Stewart Brodie's avatar
Stewart Brodie committed
256 257 258
        if(!__ROM) _swix(TinySupport_Die, 0);
        #endif
        #endif
Stewart Brodie's avatar
Stewart Brodie committed
259

Stewart Brodie's avatar
Stewart Brodie committed
260
        return NULL;
261 262 263 264 265
}


_kernel_oserror *swi_handler(int swi_offset, _kernel_swi_regs *r, void *pw)
{
Stewart Brodie's avatar
Stewart Brodie committed
266
        (void) pw;
267

Stewart Brodie's avatar
Stewart Brodie committed
268 269 270
        switch (swi_offset) {
                case GenericFetcher_GetData - GenericFetcher_00:
                        return(generic_start(r));
271

Stewart Brodie's avatar
Stewart Brodie committed
272 273
                case GenericFetcher_Status - GenericFetcher_00:
                        return(generic_status(r));
274

Stewart Brodie's avatar
Stewart Brodie committed
275 276
                case GenericFetcher_ReadData - GenericFetcher_00:
                        return(generic_readdata(r));
277

Stewart Brodie's avatar
Stewart Brodie committed
278 279
                case GenericFetcher_Stop - GenericFetcher_00:
                       return (generic_stop(r));
280

Stewart Brodie's avatar
Stewart Brodie committed
281 282 283
                default:
                        return(error_BAD_SWI);
        }
284 285 286 287 288
}


int callback_handler(_kernel_swi_regs *r, void *pw)
{
Stewart Brodie's avatar
Stewart Brodie committed
289 290
        (void) pw;
        (void) r;
291

Stewart Brodie's avatar
Stewart Brodie committed
292 293 294
        if (!callback_pending_flag) {
                return 1;
        }
295

Stewart Brodie's avatar
Stewart Brodie committed
296 297
        callback_pending_flag = 0;
        return 1;
298 299 300 301
}

int callevery_handler(_kernel_swi_regs *r, void *pw)
{
Stewart Brodie's avatar
Stewart Brodie committed
302 303 304 305 306 307 308
        (void) r;
        if (callback_pending_flag) {
                return 1;
        }
        callback_pending_flag = 1;
        (void) _swix(OS_AddCallBack, _INR(0,1), callback_entry, pw);
        return 1;
309 310 311 312 313
}

/* RISC OS 3.1 SVC mode realloc is broken, so we must provide our own */
char *module_realloc(void *ptr, size_t size)
{
Stewart Brodie's avatar
Stewart Brodie committed
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
        dprintf(("module_1", "module_realloc(%p, %d)\n", ptr, size));
        if (!clibrary_realloc_routine_is_buggy) return realloc(ptr, size);

        if (ptr == NULL) {
                return malloc(size);
        }
        if (size == 0) {
                free(ptr);
                return NULL;
        }
        else {
                const int *rma_block = ptr;
                const size_t newsize = size - (rma_block[-1] - 4);
                char *newptr;

                if (_swix(OS_Module, _IN(0)|_INR(2,3)|_OUT(2), 0xD, ptr, newsize, &newptr) != NULL) {
                        return NULL;
                }

                return newptr;
        }
335
}