Release 4.16 drivers/visorbus/visorchannel.c
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2010 - 2015 UNISYS CORPORATION
* All rights reserved.
*/
/*
* This provides s-Par channel communication primitives, which are
* independent of the mechanism used to access the channel data.
*/
#include <linux/uuid.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/visorbus.h>
#include "visorbus_private.h"
#include "controlvmchannel.h"
#define VISOR_DRV_NAME "visorchannel"
#define VISOR_CONSOLEVIDEO_CHANNEL_GUID \
GUID_INIT(0x3cd6e705, 0xd6a2, 0x4aa5, \
0xad, 0x5c, 0x7b, 0x8, 0x88, 0x9d, 0xff, 0xe2)
static const guid_t visor_video_guid = VISOR_CONSOLEVIDEO_CHANNEL_GUID;
struct visorchannel {
u64 physaddr;
ulong nbytes;
void *mapped;
bool requested;
struct channel_header chan_hdr;
guid_t guid;
/*
* channel creator knows if more than one thread will be inserting or
* removing
*/
bool needs_lock;
/* protect head writes in chan_hdr */
spinlock_t insert_lock;
/* protect tail writes in chan_hdr */
spinlock_t remove_lock;
guid_t type;
guid_t inst;
};
void visorchannel_destroy(struct visorchannel *channel)
{
if (!channel)
return;
if (channel->mapped) {
memunmap(channel->mapped);
if (channel->requested)
release_mem_region(channel->physaddr, channel->nbytes);
}
kfree(channel);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David Kershner | 25 | 47.17% | 2 | 22.22% |
Jes Sorensen | 12 | 22.64% | 2 | 22.22% |
Ken Cox | 10 | 18.87% | 1 | 11.11% |
Bryan Thompson | 2 | 3.77% | 1 | 11.11% |
Prarit Bhargava | 2 | 3.77% | 1 | 11.11% |
Charles Daniels | 1 | 1.89% | 1 | 11.11% |
Benjamin Romer | 1 | 1.89% | 1 | 11.11% |
Total | 53 | 100.00% | 9 | 100.00% |
u64 visorchannel_get_physaddr(struct visorchannel *channel)
{
return channel->physaddr;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David Kershner | 11 | 73.33% | 1 | 33.33% |
Jes Sorensen | 3 | 20.00% | 1 | 33.33% |
Charles Daniels | 1 | 6.67% | 1 | 33.33% |
Total | 15 | 100.00% | 3 | 100.00% |
ulong visorchannel_get_nbytes(struct visorchannel *channel)
{
return channel->nbytes;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David Kershner | 11 | 73.33% | 1 | 33.33% |
Jes Sorensen | 3 | 20.00% | 1 | 33.33% |
Charles Daniels | 1 | 6.67% | 1 | 33.33% |
Total | 15 | 100.00% | 3 | 100.00% |
char *visorchannel_guid_id(const guid_t *guid, char *s)
{
sprintf(s, "%pUL", guid);
return s;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David Kershner | 21 | 77.78% | 1 | 33.33% |
Andy Shevchenko | 3 | 11.11% | 1 | 33.33% |
Ken Cox | 3 | 11.11% | 1 | 33.33% |
Total | 27 | 100.00% | 3 | 100.00% |
char *visorchannel_id(struct visorchannel *channel, char *s)
{
return visorchannel_guid_id(&channel->guid, s);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David Kershner | 18 | 69.23% | 1 | 25.00% |
Ken Cox | 6 | 23.08% | 1 | 25.00% |
Andy Shevchenko | 1 | 3.85% | 1 | 25.00% |
Prarit Bhargava | 1 | 3.85% | 1 | 25.00% |
Total | 26 | 100.00% | 4 | 100.00% |
char *visorchannel_zoneid(struct visorchannel *channel, char *s)
{
return visorchannel_guid_id(&channel->chan_hdr.zone_guid, s);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Ken Cox | 24 | 85.71% | 1 | 33.33% |
Andy Shevchenko | 2 | 7.14% | 1 | 33.33% |
Bryan Thompson | 2 | 7.14% | 1 | 33.33% |
Total | 28 | 100.00% | 3 | 100.00% |
u64 visorchannel_get_clientpartition(struct visorchannel *channel)
{
return channel->chan_hdr.partition_handle;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Ken Cox | 13 | 76.47% | 1 | 25.00% |
Bryan Thompson | 2 | 11.76% | 1 | 25.00% |
Charles Daniels | 1 | 5.88% | 1 | 25.00% |
Benjamin Romer | 1 | 5.88% | 1 | 25.00% |
Total | 17 | 100.00% | 4 | 100.00% |
int visorchannel_set_clientpartition(struct visorchannel *channel,
u64 partition_handle)
{
channel->chan_hdr.partition_handle = partition_handle;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Don Zickus | 23 | 95.83% | 1 | 50.00% |
Charles Daniels | 1 | 4.17% | 1 | 50.00% |
Total | 24 | 100.00% | 2 | 100.00% |
/**
* visorchannel_get_guid() - queries the GUID of the designated channel
* @channel: the channel to query
*
* Return: the GUID of the provided channel
*/
const guid_t *visorchannel_get_guid(struct visorchannel *channel)
{
return &channel->guid;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Ken Cox | 11 | 61.11% | 1 | 33.33% |
Andy Shevchenko | 5 | 27.78% | 1 | 33.33% |
Bryan Thompson | 2 | 11.11% | 1 | 33.33% |
Total | 18 | 100.00% | 3 | 100.00% |
EXPORT_SYMBOL_GPL(visorchannel_get_guid);
int visorchannel_read(struct visorchannel *channel, ulong offset, void *dest,
ulong nbytes)
{
if (offset + nbytes > channel->nbytes)
return -EIO;
memcpy(dest, channel->mapped + offset, nbytes);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Ken Cox | 29 | 58.00% | 1 | 16.67% |
Jes Sorensen | 15 | 30.00% | 1 | 16.67% |
Erik Arfvidson | 2 | 4.00% | 1 | 16.67% |
Bryan Thompson | 2 | 4.00% | 1 | 16.67% |
Dan J Williams | 1 | 2.00% | 1 | 16.67% |
Charles Daniels | 1 | 2.00% | 1 | 16.67% |
Total | 50 | 100.00% | 6 | 100.00% |
int visorchannel_write(struct visorchannel *channel, ulong offset, void *dest,
ulong nbytes)
{
size_t chdr_size = sizeof(struct channel_header);
size_t copy_size;
if (offset + nbytes > channel->nbytes)
return -EIO;
if (offset < chdr_size) {
copy_size = min(chdr_size - offset, nbytes);
memcpy(((char *)(&channel->chan_hdr)) + offset,
dest, copy_size);
}
memcpy(channel->mapped + offset, dest, nbytes);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jes Sorensen | 41 | 39.81% | 3 | 30.00% |
Ken Cox | 39 | 37.86% | 1 | 10.00% |
Prarit Bhargava | 8 | 7.77% | 1 | 10.00% |
Tim Sell | 8 | 7.77% | 1 | 10.00% |
Erik Arfvidson | 3 | 2.91% | 1 | 10.00% |
Bryan Thompson | 2 | 1.94% | 1 | 10.00% |
Dan J Williams | 1 | 0.97% | 1 | 10.00% |
Charles Daniels | 1 | 0.97% | 1 | 10.00% |
Total | 103 | 100.00% | 10 | 100.00% |
void *visorchannel_get_header(struct visorchannel *channel)
{
return &channel->chan_hdr;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Ken Cox | 15 | 88.24% | 1 | 50.00% |
Bryan Thompson | 2 | 11.76% | 1 | 50.00% |
Total | 17 | 100.00% | 2 | 100.00% |
/*
* Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
* channel header
*/
static int sig_queue_offset(struct channel_header *chan_hdr, int q)
{
return ((chan_hdr)->ch_space_offset +
((q) * sizeof(struct signal_queue_header)));
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David Kershner | 29 | 82.86% | 1 | 33.33% |
Ken Cox | 5 | 14.29% | 1 | 33.33% |
Colin Ian King | 1 | 2.86% | 1 | 33.33% |
Total | 35 | 100.00% | 3 | 100.00% |
/*
* Return offset of a specific queue entry (data) from the beginning of a
* channel header
*/
static int sig_data_offset(struct channel_header *chan_hdr, int q,
struct signal_queue_header *sig_hdr, int slot)
{
return (sig_queue_offset(chan_hdr, q) + sig_hdr->sig_base_offset +
(slot * sig_hdr->signal_size));
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David Kershner | 34 | 77.27% | 1 | 33.33% |
Ken Cox | 9 | 20.45% | 1 | 33.33% |
Colin Ian King | 1 | 2.27% | 1 | 33.33% |
Total | 44 | 100.00% | 3 | 100.00% |
/*
* Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back into
* host memory
*/
#define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \
visorchannel_write(channel, \
sig_queue_offset(&channel->chan_hdr, queue) + \
offsetof(struct signal_queue_header, FIELD), \
&((sig_hdr)->FIELD), \
sizeof((sig_hdr)->FIELD))
static int sig_read_header(struct visorchannel *channel, u32 queue,
struct signal_queue_header *sig_hdr)
{
if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
return -EINVAL;
/* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
return visorchannel_read(channel,
sig_queue_offset(&channel->chan_hdr, queue),
sig_hdr, sizeof(struct signal_queue_header));
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Ken Cox | 44 | 70.97% | 1 | 10.00% |
Benjamin Romer | 8 | 12.90% | 4 | 40.00% |
David Binder | 4 | 6.45% | 1 | 10.00% |
Prarit Bhargava | 2 | 3.23% | 1 | 10.00% |
Bryan Thompson | 2 | 3.23% | 1 | 10.00% |
David Kershner | 1 | 1.61% | 1 | 10.00% |
Jes Sorensen | 1 | 1.61% | 1 | 10.00% |
Total | 62 | 100.00% | 10 | 100.00% |
static int sig_read_data(struct visorchannel *channel, u32 queue,
struct signal_queue_header *sig_hdr, u32 slot,
void *data)
{
int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue,
sig_hdr, slot);
return visorchannel_read(channel, signal_data_offset,
data, sig_hdr->signal_size);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David Kershner | 54 | 94.74% | 2 | 50.00% |
David Binder | 2 | 3.51% | 1 | 25.00% |
Ken Cox | 1 | 1.75% | 1 | 25.00% |
Total | 57 | 100.00% | 4 | 100.00% |
static int sig_write_data(struct visorchannel *channel, u32 queue,
struct signal_queue_header *sig_hdr, u32 slot,
void *data)
{
int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue,
sig_hdr, slot);
return visorchannel_write(channel, signal_data_offset,
data, sig_hdr->signal_size);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Ken Cox | 43 | 75.44% | 1 | 11.11% |
Benjamin Romer | 5 | 8.77% | 3 | 33.33% |
David Kershner | 4 | 7.02% | 2 | 22.22% |
David Binder | 2 | 3.51% | 1 | 11.11% |
Bryan Thompson | 2 | 3.51% | 1 | 11.11% |
Prarit Bhargava | 1 | 1.75% | 1 | 11.11% |
Total | 57 | 100.00% | 9 | 100.00% |
static int signalremove_inner(struct visorchannel *channel, u32 queue,
void *msg)
{
struct signal_queue_header sig_hdr;
int error;
error = sig_read_header(channel, queue, &sig_hdr);
if (error)
return error;
/* No signals to remove; have caller try again. */
if (sig_hdr.head == sig_hdr.tail)
return -EAGAIN;
sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
error = sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg);
if (error)
return error;
sig_hdr.num_received++;
/*
* For each data field in SIGNAL_QUEUE_HEADER that was modified, update
* host memory. Required for channel sync.
*/
mb();
error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail);
if (error)
return error;
error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received);
if (error)
return error;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David Kershner | 107 | 69.48% | 3 | 37.50% |
David Binder | 34 | 22.08% | 1 | 12.50% |
Ken Cox | 8 | 5.19% | 1 | 12.50% |
Benjamin Romer | 3 | 1.95% | 2 | 25.00% |
Bryan Thompson | 2 | 1.30% | 1 | 12.50% |
Total | 154 | 100.00% | 8 | 100.00% |
/**
* visorchannel_signalremove() - removes a message from the designated
* channel/queue
* @channel: the channel the message will be removed from
* @queue: the queue the message will be removed from
* @msg: the message to remove
*
* Return: integer error code indicating the status of the removal
*/
int visorchannel_signalremove(struct visorchannel *channel, u32 queue,
void *msg)
{
int rc;
unsigned long flags;
if (channel->needs_lock) {
spin_lock_irqsave(&channel->remove_lock, flags);
rc = signalremove_inner(channel, queue, msg);
spin_unlock_irqrestore(&channel->remove_lock, flags);
} else {
rc = signalremove_inner(channel, queue, msg);
}
return rc;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David Kershner | 71 | 88.75% | 1 | 20.00% |
Ken Cox | 6 | 7.50% | 1 | 20.00% |
Charles Daniels | 1 | 1.25% | 1 | 20.00% |
Benjamin Romer | 1 | 1.25% | 1 | 20.00% |
David Binder | 1 | 1.25% | 1 | 20.00% |
Total | 80 | 100.00% | 5 | 100.00% |
EXPORT_SYMBOL_GPL(visorchannel_signalremove);
static bool queue_empty(struct visorchannel *channel, u32 queue)
{
struct signal_queue_header sig_hdr;
if (sig_read_header(channel, queue, &sig_hdr))
return true;
return (sig_hdr.head == sig_hdr.tail);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David Kershner | 29 | 65.91% | 1 | 25.00% |
Cathal Mullaney | 9 | 20.45% | 1 | 25.00% |
Ken Cox | 5 | 11.36% | 1 | 25.00% |
Prarit Bhargava | 1 | 2.27% | 1 | 25.00% |
Total | 44 | 100.00% | 4 | 100.00% |
/**
* visorchannel_signalempty() - checks if the designated channel/queue contains
* any messages
* @channel: the channel to query
* @queue: the queue in the channel to query
*
* Return: boolean indicating whether any messages in the designated
* channel/queue are present
*/
bool visorchannel_signalempty(struct visorchannel *channel, u32 queue)
{
bool rc;
unsigned long flags;
if (!channel->needs_lock)
return queue_empty(channel, queue);
spin_lock_irqsave(&channel->remove_lock, flags);
rc = queue_empty(channel, queue);
spin_unlock_irqrestore(&channel->remove_lock, flags);
return rc;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Cathal Mullaney | 45 | 67.16% | 1 | 25.00% |
David Kershner | 19 | 28.36% | 1 | 25.00% |
Ken Cox | 2 | 2.99% | 1 | 25.00% |
Charles Daniels | 1 | 1.49% | 1 | 25.00% |
Total | 67 | 100.00% | 4 | 100.00% |
EXPORT_SYMBOL_GPL(visorchannel_signalempty);
static int signalinsert_inner(struct visorchannel *channel, u32 queue,
void *msg)
{
struct signal_queue_header sig_hdr;
int err;
err = sig_read_header(channel, queue, &sig_hdr);
if (err)
return err;
sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots;
if (sig_hdr.head == sig_hdr.tail) {
sig_hdr.num_overflows++;
err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_overflows);
if (err)
return err;
return -EIO;
}
err = sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg);
if (err)
return err;
sig_hdr.num_sent++;
/*
* For each data field in SIGNAL_QUEUE_HEADER that was modified, update
* host memory. Required for channel sync.
*/
mb();
err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, head);
if (err)
return err;
err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent);
if (err)
return err;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Ken Cox | 77 | 42.54% | 1 | 9.09% |
David Kershner | 62 | 34.25% | 3 | 27.27% |
David Binder | 22 | 12.15% | 1 | 9.09% |
Zachary Warren | 11 | 6.08% | 1 | 9.09% |
Benjamin Romer | 7 | 3.87% | 4 | 36.36% |
Bryan Thompson | 2 | 1.10% | 1 | 9.09% |
Total | 181 | 100.00% | 11 | 100.00% |
/*
* visorchannel_create() - creates the struct visorchannel abstraction for a
* data area in memory, but does NOT modify this data
* area
* @physaddr: physical address of start of channel
* @gfp: gfp_t to use when allocating memory for the data struct
* @guid: GUID that identifies channel type;
* @needs_lock: must specify true if you have multiple threads of execution
* that will be calling visorchannel methods of this
* visorchannel at the same time
*
* Return: pointer to visorchannel that was created if successful,
* otherwise NULL
*/
struct visorchannel *visorchannel_create(u64 physaddr, gfp_t gfp,
const guid_t *guid, bool needs_lock)
{
struct visorchannel *channel;
int err;
size_t size = sizeof(struct channel_header);
if (physaddr == 0)
return NULL;
channel = kzalloc(sizeof(*channel), gfp);
if (!channel)
return NULL;
channel->needs_lock = needs_lock;
spin_lock_init(&channel->insert_lock);
spin_lock_init(&channel->remove_lock);
/*
* Video driver constains the efi framebuffer so it will get a conflict
* resource when requesting its full mem region. Since we are only
* using the efi framebuffer for video we can ignore this. Remember that
* we haven't requested it so we don't try to release later on.
*/
channel->requested = request_mem_region(physaddr, size, VISOR_DRV_NAME);
if (!channel->requested && !guid_equal(guid, &visor_video_guid))
/* we only care about errors if this is not the video channel */
goto err_destroy_channel;
channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
if (!channel->mapped) {
release_mem_region(physaddr, size);
goto err_destroy_channel;
}
channel->physaddr = physaddr;
channel->nbytes = size;
err = visorchannel_read(channel, 0, &channel->chan_hdr, size);
if (err)
goto err_destroy_channel;
size = (ulong)channel->chan_hdr.size;
memunmap(channel->mapped);
if (channel->requested)
release_mem_region(channel->physaddr, channel->nbytes);
channel->mapped = NULL;
channel->requested = request_mem_region(channel->physaddr, size,
VISOR_DRV_NAME);
if (!channel->requested && !guid_equal(guid, &visor_video_guid))
/* we only care about errors if this is not the video channel */
goto err_destroy_channel;
channel->mapped = memremap(channel->physaddr, size, MEMREMAP_WB);
if (!channel->mapped) {
release_mem_region(channel->physaddr, size);
goto err_destroy_channel;
}
channel->nbytes = size;
guid_copy(&channel->guid, guid);
return channel;
err_destroy_channel:
visorchannel_destroy(channel);
return NULL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David Kershner | 213 | 64.16% | 4 | 28.57% |
Ken Cox | 47 | 14.16% | 2 | 14.29% |
Neil Horman | 28 | 8.43% | 1 | 7.14% |
Zachary Warren | 19 | 5.72% | 1 | 7.14% |
Andy Shevchenko | 14 | 4.22% | 1 | 7.14% |
Benjamin Romer | 5 | 1.51% | 1 | 7.14% |
Sameer Wadgaonkar | 3 | 0.90% | 2 | 14.29% |
David Binder | 2 | 0.60% | 1 | 7.14% |
Tim Sell | 1 | 0.30% | 1 | 7.14% |
Total | 332 | 100.00% | 14 | 100.00% |
/**
* visorchannel_signalinsert() - inserts a message into the designated
* channel/queue
* @channel: the channel the message will be added to
* @queue: the queue the message will be added to
* @msg: the message to insert
*
* Return: integer error code indicating the status of the insertion
*/
int visorchannel_signalinsert(struct visorchannel *channel, u32 queue,
void *msg)
{
int rc;
unsigned long flags;
if (channel->needs_lock) {
spin_lock_irqsave(&channel->insert_lock, flags);
rc = signalinsert_inner(channel, queue, msg);
spin_unlock_irqrestore(&channel->insert_lock, flags);
} else {
rc = signalinsert_inner(channel, queue, msg);
}
return rc;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Zachary Warren | 51 | 63.75% | 1 | 16.67% |
Ken Cox | 17 | 21.25% | 2 | 33.33% |
Tim Sell | 10 | 12.50% | 1 | 16.67% |
David Binder | 1 | 1.25% | 1 | 16.67% |
Charles Daniels | 1 | 1.25% | 1 | 16.67% |
Total | 80 | 100.00% | 6 | 100.00% |
EXPORT_SYMBOL_GPL(visorchannel_signalinsert);
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
David Kershner | 738 | 43.21% | 10 | 17.54% |
Ken Cox | 460 | 26.93% | 2 | 3.51% |
Jes Sorensen | 83 | 4.86% | 8 | 14.04% |
Zachary Warren | 81 | 4.74% | 1 | 1.75% |
David Binder | 74 | 4.33% | 5 | 8.77% |
Cathal Mullaney | 54 | 3.16% | 1 | 1.75% |
Benjamin Romer | 33 | 1.93% | 8 | 14.04% |
Andy Shevchenko | 32 | 1.87% | 1 | 1.75% |
Don Zickus | 30 | 1.76% | 2 | 3.51% |
Neil Horman | 28 | 1.64% | 1 | 1.75% |
Bryan Thompson | 23 | 1.35% | 1 | 1.75% |
Tim Sell | 19 | 1.11% | 2 | 3.51% |
Prarit Bhargava | 16 | 0.94% | 4 | 7.02% |
Charles Daniels | 10 | 0.59% | 1 | 1.75% |
Sameer Wadgaonkar | 9 | 0.53% | 3 | 5.26% |
Erik Arfvidson | 6 | 0.35% | 2 | 3.51% |
Dan J Williams | 5 | 0.29% | 1 | 1.75% |
Laurent Navet | 3 | 0.18% | 1 | 1.75% |
Colin Ian King | 2 | 0.12% | 1 | 1.75% |
Greg Kroah-Hartman | 2 | 0.12% | 2 | 3.51% |
Total | 1708 | 100.00% | 57 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.