OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [watchdog/] [wdrtas.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * FIXME: add wdrtas_get_status and wdrtas_get_boot_status as soon as
3
 * RTAS calls are available
4
 */
5
 
6
/*
7
 * RTAS watchdog driver
8
 *
9
 * (C) Copyright IBM Corp. 2005
10
 * device driver to exploit watchdog RTAS functions
11
 *
12
 * Authors : Utz Bacher <utz.bacher@de.ibm.com>
13
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 2, or (at your option)
17
 * any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27
 */
28
 
29
#include <linux/fs.h>
30
#include <linux/init.h>
31
#include <linux/kernel.h>
32
#include <linux/miscdevice.h>
33
#include <linux/module.h>
34
#include <linux/notifier.h>
35
#include <linux/reboot.h>
36
#include <linux/types.h>
37
#include <linux/watchdog.h>
38
 
39
#include <asm/rtas.h>
40
#include <asm/uaccess.h>
41
 
42
#define WDRTAS_MAGIC_CHAR               42
43
#define WDRTAS_SUPPORTED_MASK           (WDIOF_SETTIMEOUT | \
44
                                         WDIOF_MAGICCLOSE)
45
 
46
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
47
MODULE_DESCRIPTION("RTAS watchdog driver");
48
MODULE_LICENSE("GPL");
49
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
50
MODULE_ALIAS_MISCDEV(TEMP_MINOR);
51
 
52
#ifdef CONFIG_WATCHDOG_NOWAYOUT
53
static int wdrtas_nowayout = 1;
54
#else
55
static int wdrtas_nowayout = 0;
56
#endif
57
 
58
static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0);
59
static char wdrtas_expect_close = 0;
60
 
61
static int wdrtas_interval;
62
 
63
#define WDRTAS_THERMAL_SENSOR           3
64
static int wdrtas_token_get_sensor_state;
65
#define WDRTAS_SURVEILLANCE_IND         9000
66
static int wdrtas_token_set_indicator;
67
#define WDRTAS_SP_SPI                   28
68
static int wdrtas_token_get_sp;
69
static int wdrtas_token_event_scan;
70
 
71
#define WDRTAS_DEFAULT_INTERVAL         300
72
 
73
#define WDRTAS_LOGBUFFER_LEN            128
74
static char wdrtas_logbuffer[WDRTAS_LOGBUFFER_LEN];
75
 
76
 
77
/*** watchdog access functions */
78
 
79
/**
80
 * wdrtas_set_interval - sets the watchdog interval
81
 * @interval: new interval
82
 *
83
 * returns 0 on success, <0 on failures
84
 *
85
 * wdrtas_set_interval sets the watchdog keepalive interval by calling the
86
 * RTAS function set-indicator (surveillance). The unit of interval is
87
 * seconds.
88
 */
89
static int
90
wdrtas_set_interval(int interval)
91
{
92
        long result;
93
        static int print_msg = 10;
94
 
95
        /* rtas uses minutes */
96
        interval = (interval + 59) / 60;
97
 
98
        result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL,
99
                           WDRTAS_SURVEILLANCE_IND, 0, interval);
100
        if ( (result < 0) && (print_msg) ) {
101
                printk(KERN_ERR "wdrtas: setting the watchdog to %i "
102
                       "timeout failed: %li\n", interval, result);
103
                print_msg--;
104
        }
105
 
106
        return result;
107
}
108
 
109
/**
110
 * wdrtas_get_interval - returns the current watchdog interval
111
 * @fallback_value: value (in seconds) to use, if the RTAS call fails
112
 *
113
 * returns the interval
114
 *
115
 * wdrtas_get_interval returns the current watchdog keepalive interval
116
 * as reported by the RTAS function ibm,get-system-parameter. The unit
117
 * of the return value is seconds.
118
 */
119
static int
120
wdrtas_get_interval(int fallback_value)
121
{
122
        long result;
123
        char value[4];
124
 
125
        result = rtas_call(wdrtas_token_get_sp, 3, 1, NULL,
126
                           WDRTAS_SP_SPI, (void *)__pa(&value), 4);
127
        if ( (value[0] != 0) || (value[1] != 2) || (value[3] != 0) ||
128
             (result < 0) ) {
129
                printk(KERN_WARNING "wdrtas: could not get sp_spi watchdog "
130
                       "timeout (%li). Continuing\n", result);
131
                return fallback_value;
132
        }
133
 
134
        /* rtas uses minutes */
135
        return ((int)value[2]) * 60;
136
}
137
 
138
/**
139
 * wdrtas_timer_start - starts watchdog
140
 *
141
 * wdrtas_timer_start starts the watchdog by calling the RTAS function
142
 * set-interval (surveillance)
143
 */
144
static void
145
wdrtas_timer_start(void)
146
{
147
        wdrtas_set_interval(wdrtas_interval);
148
}
149
 
150
/**
151
 * wdrtas_timer_stop - stops watchdog
152
 *
153
 * wdrtas_timer_stop stops the watchdog timer by calling the RTAS function
154
 * set-interval (surveillance)
155
 */
156
static void
157
wdrtas_timer_stop(void)
158
{
159
        wdrtas_set_interval(0);
160
}
161
 
162
/**
163
 * wdrtas_log_scanned_event - logs an event we received during keepalive
164
 *
165
 * wdrtas_log_scanned_event prints a message to the log buffer dumping
166
 * the results of the last event-scan call
167
 */
168
static void
169
wdrtas_log_scanned_event(void)
170
{
171
        int i;
172
 
173
        for (i = 0; i < WDRTAS_LOGBUFFER_LEN; i += 16)
174
                printk(KERN_INFO "wdrtas: dumping event (line %i/%i), data = "
175
                       "%02x %02x %02x %02x  %02x %02x %02x %02x   "
176
                       "%02x %02x %02x %02x  %02x %02x %02x %02x\n",
177
                       (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16),
178
                       wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1],
179
                       wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3],
180
                       wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5],
181
                       wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7],
182
                       wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9],
183
                       wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11],
184
                       wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13],
185
                       wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]);
186
}
187
 
188
/**
189
 * wdrtas_timer_keepalive - resets watchdog timer to keep system alive
190
 *
191
 * wdrtas_timer_keepalive restarts the watchdog timer by calling the
192
 * RTAS function event-scan and repeats these calls as long as there are
193
 * events available. All events will be dumped.
194
 */
195
static void
196
wdrtas_timer_keepalive(void)
197
{
198
        long result;
199
 
200
        do {
201
                result = rtas_call(wdrtas_token_event_scan, 4, 1, NULL,
202
                                   RTAS_EVENT_SCAN_ALL_EVENTS, 0,
203
                                   (void *)__pa(wdrtas_logbuffer),
204
                                   WDRTAS_LOGBUFFER_LEN);
205
                if (result < 0)
206
                        printk(KERN_ERR "wdrtas: event-scan failed: %li\n",
207
                               result);
208
                if (result == 0)
209
                        wdrtas_log_scanned_event();
210
        } while (result == 0);
211
}
212
 
213
/**
214
 * wdrtas_get_temperature - returns current temperature
215
 *
216
 * returns temperature or <0 on failures
217
 *
218
 * wdrtas_get_temperature returns the current temperature in Fahrenheit. It
219
 * uses the RTAS call get-sensor-state, token 3 to do so
220
 */
221
static int
222
wdrtas_get_temperature(void)
223
{
224
        long result;
225
        int temperature = 0;
226
 
227
        result = rtas_call(wdrtas_token_get_sensor_state, 2, 2,
228
                           (void *)__pa(&temperature),
229
                           WDRTAS_THERMAL_SENSOR, 0);
230
 
231
        if (result < 0)
232
                printk(KERN_WARNING "wdrtas: reading the thermal sensor "
233
                       "faild: %li\n", result);
234
        else
235
                temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */
236
 
237
        return temperature;
238
}
239
 
240
/**
241
 * wdrtas_get_status - returns the status of the watchdog
242
 *
243
 * returns a bitmask of defines WDIOF_... as defined in
244
 * include/linux/watchdog.h
245
 */
246
static int
247
wdrtas_get_status(void)
248
{
249
        return 0; /* TODO */
250
}
251
 
252
/**
253
 * wdrtas_get_boot_status - returns the reason for the last boot
254
 *
255
 * returns a bitmask of defines WDIOF_... as defined in
256
 * include/linux/watchdog.h, indicating why the watchdog rebooted the system
257
 */
258
static int
259
wdrtas_get_boot_status(void)
260
{
261
        return 0; /* TODO */
262
}
263
 
264
/*** watchdog API and operations stuff */
265
 
266
/* wdrtas_write - called when watchdog device is written to
267
 * @file: file structure
268
 * @buf: user buffer with data
269
 * @len: amount to data written
270
 * @ppos: position in file
271
 *
272
 * returns the number of successfully processed characters, which is always
273
 * the number of bytes passed to this function
274
 *
275
 * wdrtas_write processes all the data given to it and looks for the magic
276
 * character 'V'. This character allows the watchdog device to be closed
277
 * properly.
278
 */
279
static ssize_t
280
wdrtas_write(struct file *file, const char __user *buf,
281
             size_t len, loff_t *ppos)
282
{
283
        int i;
284
        char c;
285
 
286
        if (!len)
287
                goto out;
288
 
289
        if (!wdrtas_nowayout) {
290
                wdrtas_expect_close = 0;
291
                /* look for 'V' */
292
                for (i = 0; i < len; i++) {
293
                        if (get_user(c, buf + i))
294
                                return -EFAULT;
295
                        /* allow to close device */
296
                        if (c == 'V')
297
                                wdrtas_expect_close = WDRTAS_MAGIC_CHAR;
298
                }
299
        }
300
 
301
        wdrtas_timer_keepalive();
302
 
303
out:
304
        return len;
305
}
306
 
307
/**
308
 * wdrtas_ioctl - ioctl function for the watchdog device
309
 * @inode: inode structure
310
 * @file: file structure
311
 * @cmd: command for ioctl
312
 * @arg: argument pointer
313
 *
314
 * returns 0 on success, <0 on failure
315
 *
316
 * wdrtas_ioctl implements the watchdog API ioctls
317
 */
318
static int
319
wdrtas_ioctl(struct inode *inode, struct file *file,
320
             unsigned int cmd, unsigned long arg)
321
{
322
        int __user *argp = (void __user *)arg;
323
        int i;
324
        static struct watchdog_info wdinfo = {
325
                .options = WDRTAS_SUPPORTED_MASK,
326
                .firmware_version = 0,
327
                .identity = "wdrtas"
328
        };
329
 
330
        switch (cmd) {
331
        case WDIOC_GETSUPPORT:
332
                if (copy_to_user(argp, &wdinfo, sizeof(wdinfo)))
333
                        return -EFAULT;
334
                return 0;
335
 
336
        case WDIOC_GETSTATUS:
337
                i = wdrtas_get_status();
338
                return put_user(i, argp);
339
 
340
        case WDIOC_GETBOOTSTATUS:
341
                i = wdrtas_get_boot_status();
342
                return put_user(i, argp);
343
 
344
        case WDIOC_GETTEMP:
345
                if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE)
346
                        return -EOPNOTSUPP;
347
 
348
                i = wdrtas_get_temperature();
349
                return put_user(i, argp);
350
 
351
        case WDIOC_SETOPTIONS:
352
                if (get_user(i, argp))
353
                        return -EFAULT;
354
                if (i & WDIOS_DISABLECARD)
355
                        wdrtas_timer_stop();
356
                if (i & WDIOS_ENABLECARD) {
357
                        wdrtas_timer_keepalive();
358
                        wdrtas_timer_start();
359
                }
360
                if (i & WDIOS_TEMPPANIC) {
361
                        /* not implemented. Done by H8 */
362
                }
363
                return 0;
364
 
365
        case WDIOC_KEEPALIVE:
366
                wdrtas_timer_keepalive();
367
                return 0;
368
 
369
        case WDIOC_SETTIMEOUT:
370
                if (get_user(i, argp))
371
                        return -EFAULT;
372
 
373
                if (wdrtas_set_interval(i))
374
                        return -EINVAL;
375
 
376
                wdrtas_timer_keepalive();
377
 
378
                if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
379
                        wdrtas_interval = i;
380
                else
381
                        wdrtas_interval = wdrtas_get_interval(i);
382
                /* fallthrough */
383
 
384
        case WDIOC_GETTIMEOUT:
385
                return put_user(wdrtas_interval, argp);
386
 
387
        default:
388
                return -ENOTTY;
389
        }
390
}
391
 
392
/**
393
 * wdrtas_open - open function of watchdog device
394
 * @inode: inode structure
395
 * @file: file structure
396
 *
397
 * returns 0 on success, -EBUSY if the file has been opened already, <0 on
398
 * other failures
399
 *
400
 * function called when watchdog device is opened
401
 */
402
static int
403
wdrtas_open(struct inode *inode, struct file *file)
404
{
405
        /* only open once */
406
        if (atomic_inc_return(&wdrtas_miscdev_open) > 1) {
407
                atomic_dec(&wdrtas_miscdev_open);
408
                return -EBUSY;
409
        }
410
 
411
        wdrtas_timer_start();
412
        wdrtas_timer_keepalive();
413
 
414
        return nonseekable_open(inode, file);
415
}
416
 
417
/**
418
 * wdrtas_close - close function of watchdog device
419
 * @inode: inode structure
420
 * @file: file structure
421
 *
422
 * returns 0 on success
423
 *
424
 * close function. Always succeeds
425
 */
426
static int
427
wdrtas_close(struct inode *inode, struct file *file)
428
{
429
        /* only stop watchdog, if this was announced using 'V' before */
430
        if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR)
431
                wdrtas_timer_stop();
432
        else {
433
                printk(KERN_WARNING "wdrtas: got unexpected close. Watchdog "
434
                       "not stopped.\n");
435
                wdrtas_timer_keepalive();
436
        }
437
 
438
        wdrtas_expect_close = 0;
439
        atomic_dec(&wdrtas_miscdev_open);
440
        return 0;
441
}
442
 
443
/**
444
 * wdrtas_temp_read - gives back the temperature in fahrenheit
445
 * @file: file structure
446
 * @buf: user buffer
447
 * @count: number of bytes to be read
448
 * @ppos: position in file
449
 *
450
 * returns always 1 or -EFAULT in case of user space copy failures, <0 on
451
 * other failures
452
 *
453
 * wdrtas_temp_read gives the temperature to the users by copying this
454
 * value as one byte into the user space buffer. The unit is Fahrenheit...
455
 */
456
static ssize_t
457
wdrtas_temp_read(struct file *file, char __user *buf,
458
                 size_t count, loff_t *ppos)
459
{
460
        int temperature = 0;
461
 
462
        temperature = wdrtas_get_temperature();
463
        if (temperature < 0)
464
                return temperature;
465
 
466
        if (copy_to_user(buf, &temperature, 1))
467
                return -EFAULT;
468
 
469
        return 1;
470
}
471
 
472
/**
473
 * wdrtas_temp_open - open function of temperature device
474
 * @inode: inode structure
475
 * @file: file structure
476
 *
477
 * returns 0 on success, <0 on failure
478
 *
479
 * function called when temperature device is opened
480
 */
481
static int
482
wdrtas_temp_open(struct inode *inode, struct file *file)
483
{
484
        return nonseekable_open(inode, file);
485
}
486
 
487
/**
488
 * wdrtas_temp_close - close function of temperature device
489
 * @inode: inode structure
490
 * @file: file structure
491
 *
492
 * returns 0 on success
493
 *
494
 * close function. Always succeeds
495
 */
496
static int
497
wdrtas_temp_close(struct inode *inode, struct file *file)
498
{
499
        return 0;
500
}
501
 
502
/**
503
 * wdrtas_reboot - reboot notifier function
504
 * @nb: notifier block structure
505
 * @code: reboot code
506
 * @ptr: unused
507
 *
508
 * returns NOTIFY_DONE
509
 *
510
 * wdrtas_reboot stops the watchdog in case of a reboot
511
 */
512
static int
513
wdrtas_reboot(struct notifier_block *this, unsigned long code, void *ptr)
514
{
515
        if ( (code==SYS_DOWN) || (code==SYS_HALT) )
516
                wdrtas_timer_stop();
517
 
518
        return NOTIFY_DONE;
519
}
520
 
521
/*** initialization stuff */
522
 
523
static const struct file_operations wdrtas_fops = {
524
        .owner          = THIS_MODULE,
525
        .llseek         = no_llseek,
526
        .write          = wdrtas_write,
527
        .ioctl          = wdrtas_ioctl,
528
        .open           = wdrtas_open,
529
        .release        = wdrtas_close,
530
};
531
 
532
static struct miscdevice wdrtas_miscdev = {
533
        .minor =        WATCHDOG_MINOR,
534
        .name =         "watchdog",
535
        .fops =         &wdrtas_fops,
536
};
537
 
538
static const struct file_operations wdrtas_temp_fops = {
539
        .owner          = THIS_MODULE,
540
        .llseek         = no_llseek,
541
        .read           = wdrtas_temp_read,
542
        .open           = wdrtas_temp_open,
543
        .release        = wdrtas_temp_close,
544
};
545
 
546
static struct miscdevice wdrtas_tempdev = {
547
        .minor =        TEMP_MINOR,
548
        .name =         "temperature",
549
        .fops =         &wdrtas_temp_fops,
550
};
551
 
552
static struct notifier_block wdrtas_notifier = {
553
        .notifier_call =        wdrtas_reboot,
554
};
555
 
556
/**
557
 * wdrtas_get_tokens - reads in RTAS tokens
558
 *
559
 * returns 0 on succes, <0 on failure
560
 *
561
 * wdrtas_get_tokens reads in the tokens for the RTAS calls used in
562
 * this watchdog driver. It tolerates, if "get-sensor-state" and
563
 * "ibm,get-system-parameter" are not available.
564
 */
565
static int
566
wdrtas_get_tokens(void)
567
{
568
        wdrtas_token_get_sensor_state = rtas_token("get-sensor-state");
569
        if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) {
570
                printk(KERN_WARNING "wdrtas: couldn't get token for "
571
                       "get-sensor-state. Trying to continue without "
572
                       "temperature support.\n");
573
        }
574
 
575
        wdrtas_token_get_sp = rtas_token("ibm,get-system-parameter");
576
        if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE) {
577
                printk(KERN_WARNING "wdrtas: couldn't get token for "
578
                       "ibm,get-system-parameter. Trying to continue with "
579
                       "a default timeout value of %i seconds.\n",
580
                       WDRTAS_DEFAULT_INTERVAL);
581
        }
582
 
583
        wdrtas_token_set_indicator = rtas_token("set-indicator");
584
        if (wdrtas_token_set_indicator == RTAS_UNKNOWN_SERVICE) {
585
                printk(KERN_ERR "wdrtas: couldn't get token for "
586
                       "set-indicator. Terminating watchdog code.\n");
587
                return -EIO;
588
        }
589
 
590
        wdrtas_token_event_scan = rtas_token("event-scan");
591
        if (wdrtas_token_event_scan == RTAS_UNKNOWN_SERVICE) {
592
                printk(KERN_ERR "wdrtas: couldn't get token for event-scan. "
593
                       "Terminating watchdog code.\n");
594
                return -EIO;
595
        }
596
 
597
        return 0;
598
}
599
 
600
/**
601
 * wdrtas_unregister_devs - unregisters the misc dev handlers
602
 *
603
 * wdrtas_register_devs unregisters the watchdog and temperature watchdog
604
 * misc devs
605
 */
606
static void
607
wdrtas_unregister_devs(void)
608
{
609
        misc_deregister(&wdrtas_miscdev);
610
        if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE)
611
                misc_deregister(&wdrtas_tempdev);
612
}
613
 
614
/**
615
 * wdrtas_register_devs - registers the misc dev handlers
616
 *
617
 * returns 0 on succes, <0 on failure
618
 *
619
 * wdrtas_register_devs registers the watchdog and temperature watchdog
620
 * misc devs
621
 */
622
static int
623
wdrtas_register_devs(void)
624
{
625
        int result;
626
 
627
        result = misc_register(&wdrtas_miscdev);
628
        if (result) {
629
                printk(KERN_ERR "wdrtas: couldn't register watchdog misc "
630
                       "device. Terminating watchdog code.\n");
631
                return result;
632
        }
633
 
634
        if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) {
635
                result = misc_register(&wdrtas_tempdev);
636
                if (result) {
637
                        printk(KERN_WARNING "wdrtas: couldn't register "
638
                               "watchdog temperature misc device. Continuing "
639
                               "without temperature support.\n");
640
                        wdrtas_token_get_sensor_state = RTAS_UNKNOWN_SERVICE;
641
                }
642
        }
643
 
644
        return 0;
645
}
646
 
647
/**
648
 * wdrtas_init - init function of the watchdog driver
649
 *
650
 * returns 0 on succes, <0 on failure
651
 *
652
 * registers the file handlers and the reboot notifier
653
 */
654
static int __init
655
wdrtas_init(void)
656
{
657
        if (wdrtas_get_tokens())
658
                return -ENODEV;
659
 
660
        if (wdrtas_register_devs())
661
                return -ENODEV;
662
 
663
        if (register_reboot_notifier(&wdrtas_notifier)) {
664
                printk(KERN_ERR "wdrtas: could not register reboot notifier. "
665
                       "Terminating watchdog code.\n");
666
                wdrtas_unregister_devs();
667
                return -ENODEV;
668
        }
669
 
670
        if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
671
                wdrtas_interval = WDRTAS_DEFAULT_INTERVAL;
672
        else
673
                wdrtas_interval = wdrtas_get_interval(WDRTAS_DEFAULT_INTERVAL);
674
 
675
        return 0;
676
}
677
 
678
/**
679
 * wdrtas_exit - exit function of the watchdog driver
680
 *
681
 * unregisters the file handlers and the reboot notifier
682
 */
683
static void __exit
684
wdrtas_exit(void)
685
{
686
        if (!wdrtas_nowayout)
687
                wdrtas_timer_stop();
688
 
689
        wdrtas_unregister_devs();
690
 
691
        unregister_reboot_notifier(&wdrtas_notifier);
692
}
693
 
694
module_init(wdrtas_init);
695
module_exit(wdrtas_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.