Annotation of linux/kernel/blk_drv/scsi/ultrastor.c, revision 1.1.1.3

1.1       root        1: /*
1.1.1.3 ! root        2:  *     ultrastor.c     Copyright (C) 1991, 1992 David B. Gentzel
1.1.1.2   root        3:  *     Low-level SCSI driver for UltraStor 14F
1.1       root        4:  *     by David B. Gentzel, Whitfield Software Services, Carnegie, PA
                      5:  *         ([email protected])
                      6:  *     Thanks to UltraStor for providing the necessary documentation
                      7:  */
                      8: 
1.1.1.2   root        9: /*
                     10:  * NOTES:
                     11:  *    The UltraStor 14F is an intelligent, high performance ISA SCSI-2 host
                     12:  *    adapter.  It is essentially an ISA version of the UltraStor 24F EISA
                     13:  *    adapter.  It supports first-party DMA, command queueing, and
                     14:  *    scatter/gather I/O.  It can also emulate the standard AT MFM/RLL/IDE
                     15:  *    interface for use with OS's which don't support SCSI.
                     16:  *
                     17:  *    This driver may also work (with some small changes) with the UltraStor
                     18:  *    24F.  I have no way of confirming this...
                     19:  *
                     20:  *    Places flagged with a triple question-mark are things which are either
                     21:  *    unfinished, questionable, or wrong.
                     22:  */
                     23: 
                     24: /*
                     25:  * CAVEATS: ???
                     26:  *    This driver is VERY stupid.  It takes no advantage of much of the power
                     27:  *    of the UltraStor controller.  We just sit-and-spin while waiting for
                     28:  *    commands to complete.  I hope to go back and beat it into shape, but
                     29:  *    PLEASE, anyone else who would like to, please make improvements!
                     30:  *
1.1.1.3 ! root       31:  *    By defining NO_QUEUEING in ultrastor.h, you disable the queueing feature
        !            32:  *    of the mid-level SCSI driver.  Once I'm satisfied that the queueing
        !            33:  *    version is as stable as the non-queueing version, I'll eliminate this
        !            34:  *    option.
1.1.1.2   root       35:  */
1.1       root       36: 
                     37: #include <linux/config.h>
                     38: 
                     39: #ifdef CONFIG_SCSI_ULTRASTOR
                     40: 
1.1.1.3 ! root       41: #include <linux/stddef.h>
1.1       root       42: #include <linux/string.h>
                     43: #include <linux/sched.h>
                     44: #include <linux/kernel.h>
1.1.1.3 ! root       45: 
1.1       root       46: #include <asm/io.h>
1.1.1.2   root       47: #include <asm/system.h>
1.1       root       48: 
1.1.1.2   root       49: #define ULTRASTOR_PRIVATE      /* Get the private stuff from ultrastor.h */
1.1       root       50: #include "ultrastor.h"
                     51: #include "scsi.h"
                     52: #include "hosts.h"
                     53: 
1.1.1.2   root       54: #define VERSION "1.0 beta"
1.1       root       55: 
                     56: #define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0])
1.1.1.2   root       57: #define BIT(n) (1ul << (n))
1.1       root       58: #define BYTE(num, n) ((unsigned char)((unsigned int)(num) >> ((n) * 8)))
                     59: 
                     60: /* Simply using "unsigned long" in these structures won't work as it causes
                     61:    alignment.  Perhaps the "aligned" attribute may be used in GCC 2.0 to get
                     62:    around this, but for now I use this hack. */
                     63: typedef struct {
                     64:     unsigned char bytes[4];
                     65: } Longword;
                     66: 
1.1.1.2   root       67: /* Used to fetch the configuration info from the config i/o registers.  We
                     68:    then store (in a friendlier format) in config. */
                     69: struct config_1 {
                     70:     unsigned char bios_segment: 3;
                     71:     unsigned char reserved: 1;
                     72:     unsigned char interrupt: 2;
                     73:     unsigned char dma_channel: 2;
                     74: };
                     75: struct config_2 {
                     76:     unsigned char ha_scsi_id: 3;
                     77:     unsigned char mapping_mode: 2;
                     78:     unsigned char bios_drive_number: 1;
                     79:     unsigned char tfr_port: 2;
                     80: };
                     81: 
1.1       root       82: /* Used to store configuration info read from config i/o registers.  Most of
                     83:    this is not used yet, but might as well save it. */
                     84: struct config {
1.1.1.2   root       85:     unsigned short port_address;
                     86:     const void *bios_segment;
                     87:     unsigned char interrupt: 4;
                     88:     unsigned char dma_channel: 3;
                     89:     unsigned char ha_scsi_id: 3;
                     90:     unsigned char heads: 6;
                     91:     unsigned char sectors: 6;
                     92:     unsigned char bios_drive_number: 1;
1.1       root       93: };
                     94: 
                     95: /* MailBox SCSI Command Packet.  Basic command structure for communicating
                     96:    with controller. */
                     97: struct mscp {
                     98:     unsigned char opcode: 3;           /* type of command */
                     99:     unsigned char xdir: 2;             /* data transfer direction */
                    100:     unsigned char dcn: 1;              /* disable disconnect */
                    101:     unsigned char ca: 1;               /* use cache (if available) */
                    102:     unsigned char sg: 1;               /* scatter/gather operation */
                    103:     unsigned char target_id: 3;                /* target SCSI id */
                    104:     unsigned char ch_no: 2;            /* SCSI channel (always 0 for 14f) */
                    105:     unsigned char lun: 3;              /* logical unit number */
                    106:     Longword transfer_data;            /* transfer data pointer */
                    107:     Longword transfer_data_length;     /* length in bytes */
                    108:     Longword command_link;             /* for linking command chains */
                    109:     unsigned char scsi_command_link_id;        /* identifies command in chain */
                    110:     unsigned char number_of_sg_list;   /* (if sg is set) 8 bytes per list */
                    111:     unsigned char length_of_sense_byte;
                    112:     unsigned char length_of_scsi_cdbs; /* 6, 10, or 12 */
                    113:     unsigned char scsi_cdbs[12];       /* SCSI commands */
                    114:     unsigned char adapter_status;      /* non-zero indicates HA error */
                    115:     unsigned char target_status;       /* non-zero indicates target error */
                    116:     Longword sense_data;
                    117: };
                    118: 
                    119: /* Allowed BIOS base addresses for 14f (NULL indicates reserved) */
                    120: static const void *const bios_segment_table[8] = {
                    121:     NULL,           (void *)0xC4000, (void *)0xC8000, (void *)0xCC000,
                    122:     (void *)0xD0000, (void *)0xD4000, (void *)0xD8000, (void *)0xDC000,
                    123: };
                    124: 
                    125: /* Allowed IRQs for 14f */
                    126: static const unsigned char interrupt_table[4] = { 15, 14, 11, 10 };
                    127: 
                    128: /* Allowed DMA channels for 14f (0 indicates reserved) */
                    129: static const unsigned char dma_channel_table[4] = { 5, 6, 7, 0 };
                    130: 
1.1.1.2   root      131: /* Head/sector mappings allowed by 14f */
1.1       root      132: static const struct {
                    133:     unsigned char heads;
                    134:     unsigned char sectors;
                    135: } mapping_table[4] = { { 16, 63 }, { 64, 32 }, { 64, 63 }, { 0, 0 } };
                    136: 
                    137: /* Config info */
                    138: static struct config config;
                    139: 
                    140: /* Our index in the host adapter array maintained by higher-level driver */
                    141: static int host_number;
                    142: 
                    143: /* PORT_ADDRESS is first port address used for i/o of messages. */
                    144: #ifdef PORT_OVERRIDE
                    145: # define PORT_ADDRESS PORT_OVERRIDE
                    146: #else
1.1.1.2   root      147: # define PORT_ADDRESS (config.port_address)
1.1       root      148: #endif
                    149: 
                    150: static volatile int aborted = 0;
                    151: 
                    152: #ifndef PORT_OVERRIDE
                    153: static const unsigned short ultrastor_ports[] = {
                    154:     0x330, 0x340, 0x310, 0x230, 0x240, 0x210, 0x130, 0x140,
                    155: };
                    156: #endif
                    157: 
1.1.1.2   root      158: void ultrastor_interrupt(void);
                    159: 
                    160: static void (*ultrastor_done)(int, int) = 0;
                    161: 
1.1       root      162: static const struct {
                    163:     const char *signature;
                    164:     size_t offset;
                    165:     size_t length;
                    166: } signatures[] = {
                    167:     { "SBIOS 1.01 COPYRIGHT (C) UltraStor Corporation,1990-1992.", 0x10, 57 },
                    168: };
                    169: 
                    170: int ultrastor_14f_detect(int hostnum)
                    171: {
                    172:     size_t i;
                    173:     unsigned char in_byte;
1.1.1.2   root      174:     struct config_1 config_1;
                    175:     struct config_2 config_2;
1.1       root      176: 
1.1.1.2   root      177: #if (ULTRASTOR_DEBUG & UD_DETECT)
                    178:     printk("US14F: detect: called\n");
1.1       root      179: #endif
                    180: 
                    181: #ifndef PORT_OVERRIDE
1.1.1.2   root      182:     PORT_ADDRESS = 0;
                    183:     for (i = 0; i < ARRAY_SIZE(ultrastor_ports); i++) {
                    184:        PORT_ADDRESS = ultrastor_ports[i];
                    185: #endif
                    186: 
                    187: #if (ULTRASTOR_DEBUG & UD_DETECT)
                    188:        printk("US14F: detect: testing port address %03X\n", PORT_ADDRESS);
                    189: #endif
                    190: 
                    191:        in_byte = inb(PRODUCT_ID(PORT_ADDRESS + 0));
                    192:        if (in_byte != US14F_PRODUCT_ID_0) {
                    193: #if (ULTRASTOR_DEBUG & UD_DETECT)
                    194: # ifdef PORT_OVERRIDE
                    195:            printk("US14F: detect: wrong product ID 0 - %02X\n", in_byte);
                    196: # else
1.1.1.3 ! root      197:            printk("US14F: detect: no adapter at port %03X\n", PORT_ADDRESS);
1.1.1.2   root      198: # endif
1.1       root      199: #endif
1.1.1.2   root      200: #ifdef PORT_OVERRIDE
                    201:            return FALSE;
                    202: #else
                    203:            continue;
1.1       root      204: #endif
1.1.1.2   root      205:        }
                    206:        in_byte = inb(PRODUCT_ID(PORT_ADDRESS + 1));
                    207:        /* Only upper nibble is defined for Product ID 1 */
                    208:        if ((in_byte & 0xF0) != US14F_PRODUCT_ID_1) {
                    209: #if (ULTRASTOR_DEBUG & UD_DETECT)
                    210: # ifdef PORT_OVERRIDE
                    211:            printk("US14F: detect: wrong product ID 1 - %02X\n", in_byte);
                    212: # else
1.1.1.3 ! root      213:            printk("US14F: detect: no adapter at port %03X\n", PORT_ADDRESS);
1.1.1.2   root      214: # endif
1.1       root      215: #endif
1.1.1.2   root      216: #ifdef PORT_OVERRIDE
                    217:            return FALSE;
                    218: #else
                    219:            continue;
1.1       root      220: #endif
1.1.1.2   root      221:        }
                    222: #ifndef PORT_OVERRIDE
                    223:        break;
1.1       root      224:     }
1.1.1.2   root      225:     if (i == ARRAY_SIZE(ultrastor_ports)) {
                    226: # if (ULTRASTOR_DEBUG & UD_DETECT)
                    227:        printk("US14F: detect: no port address found!\n");
                    228: # endif
1.1       root      229:        return FALSE;
                    230:     }
1.1.1.2   root      231: #endif
                    232: 
                    233: #if (ULTRASTOR_DEBUG & UD_DETECT)
                    234:     printk("US14F: detect: adapter found at port address %03X\n",
                    235:           PORT_ADDRESS);
                    236: #endif
1.1       root      237: 
                    238:     /* All above tests passed, must be the right thing.  Get some useful
                    239:        info. */
1.1.1.2   root      240:     *(char *)&config_1 = inb(CONFIG(PORT_ADDRESS + 0));
                    241:     *(char *)&config_2 = inb(CONFIG(PORT_ADDRESS + 1));
                    242:     config.bios_segment = bios_segment_table[config_1.bios_segment];
                    243:     config.interrupt = interrupt_table[config_1.interrupt];
                    244:     config.dma_channel = dma_channel_table[config_1.dma_channel];
                    245:     config.ha_scsi_id = config_2.ha_scsi_id;
                    246:     config.heads = mapping_table[config_2.mapping_mode].heads;
                    247:     config.sectors = mapping_table[config_2.mapping_mode].sectors;
                    248:     config.bios_drive_number = config_2.bios_drive_number;
1.1       root      249: 
                    250:     /* To verify this card, we simply look for the UltraStor SCSI from the
                    251:        BIOS version notice. */
1.1.1.2   root      252:     if (config.bios_segment != NULL) {
1.1       root      253:        int found = 0;
                    254: 
                    255:        for (i = 0; !found && i < ARRAY_SIZE(signatures); i++)
1.1.1.2   root      256:            if (memcmp((char *)config.bios_segment + signatures[i].offset,
1.1       root      257:                       signatures[i].signature, signatures[i].length))
                    258:                found = 1;
                    259:        if (!found)
1.1.1.2   root      260:            config.bios_segment = NULL;
1.1       root      261:     }
1.1.1.2   root      262:     if (!config.bios_segment) {
                    263: #if (ULTRASTOR_DEBUG & UD_DETECT)
                    264:        printk("US14F: detect: not detected.\n");
1.1       root      265: #endif
                    266:        return FALSE;
                    267:     }
                    268: 
                    269:     /* Final consistancy check, verify previous info. */
1.1.1.2   root      270:     if (!config.dma_channel || !(config_2.tfr_port & 0x2)) {
                    271: #if (ULTRASTOR_DEBUG & UD_DETECT)
                    272:        printk("US14F: detect: consistancy check failed\n");
1.1       root      273: #endif
                    274:        return FALSE;
                    275:     }
                    276: 
                    277:     /* If we were TRULY paranoid, we could issue a host adapter inquiry
                    278:        command here and verify the data returned.  But frankly, I'm
                    279:        exhausted! */
                    280: 
                    281:     /* Finally!  Now I'm satisfied... */
1.1.1.2   root      282: #if (ULTRASTOR_DEBUG & UD_DETECT)
                    283:     printk("US14F: detect: detect succeeded\n"
                    284:           "  Port address: %03X\n"
1.1       root      285:           "  BIOS segment: %05X\n"
1.1.1.2   root      286:           "  Interrupt: %u\n"
                    287:           "  DMA channel: %u\n"
                    288:           "  H/A SCSI ID: %u\n",
                    289:           PORT_ADDRESS, config.bios_segment, config.interrupt,
                    290:           config.dma_channel, config.ha_scsi_id);
1.1       root      291: #endif
                    292:     host_number = hostnum;
1.1.1.2   root      293:     scsi_hosts[hostnum].this_id = config.ha_scsi_id;
1.1.1.3 ! root      294: #ifndef NO_QUEUEING
1.1.1.2   root      295:     set_intr_gate(0x20 + config.interrupt, ultrastor_interrupt);
                    296:     /* gate to PIC 2 */
                    297:     outb_p(inb_p(0x21) & ~BIT(2), 0x21);
                    298:     /* enable the interrupt */
                    299:     outb(inb_p(0xA1) & ~BIT(config.interrupt - 8), 0xA1);
                    300: #endif
1.1       root      301:     return TRUE;
                    302: }
                    303: 
                    304: const char *ultrastor_14f_info(void)
                    305: {
                    306:     return "UltraStor 14F SCSI driver version "
                    307:           VERSION
                    308:           " by David B. Gentzel\n";
                    309: }
                    310: 
1.1.1.2   root      311: static struct mscp mscp = {
                    312:     OP_SCSI, DTD_SCSI, FALSE, TRUE, FALSE      /* This stuff doesn't change */
                    313: };
                    314: 
1.1       root      315: int ultrastor_14f_queuecommand(unsigned char target, const void *cmnd,
                    316:                               void *buff, int bufflen, void (*done)(int, int))
                    317: {
                    318:     unsigned char in_byte;
                    319: 
1.1.1.2   root      320: #if (ULTRASTOR_DEBUG & UD_COMMAND)
                    321:     printk("US14F: queuecommand: called\n");
                    322: #endif
                    323: 
                    324:     /* Skip first (constant) byte */
                    325:     memset((char *)&mscp + 1, 0, sizeof (struct mscp) - 1);
                    326:     mscp.target_id = target;
                    327:     /* mscp.lun = ???; */
                    328:     mscp.transfer_data = *(Longword *)&buff;
                    329:     mscp.transfer_data_length = *(Longword *)&bufflen,
                    330:     mscp.length_of_scsi_cdbs = ((*(unsigned char *)cmnd <= 0x1F) ? 6 : 10);
1.1       root      331:     memcpy(mscp.scsi_cdbs, cmnd, mscp.length_of_scsi_cdbs);
                    332: 
                    333:     /* Find free OGM slot (OGMINT bit is 0) */
                    334:     do
1.1.1.2   root      335:        in_byte = inb_p(LCL_DOORBELL_INTR(PORT_ADDRESS));
1.1       root      336:     while (!aborted && (in_byte & 1));
1.1.1.3 ! root      337:     if (aborted) {
        !           338: #if (ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT))
        !           339:        printk("US14F: queuecommand: aborted\n");
        !           340: #endif
1.1       root      341:        /* ??? is this right? */
                    342:        return (aborted << 16);
1.1.1.3 ! root      343:     }
1.1       root      344: 
                    345:     /* Store pointer in OGM address bytes */
1.1.1.2   root      346:     outb_p(BYTE(&mscp, 0), OGM_DATA_PTR(PORT_ADDRESS + 0));
                    347:     outb_p(BYTE(&mscp, 1), OGM_DATA_PTR(PORT_ADDRESS + 1));
                    348:     outb_p(BYTE(&mscp, 2), OGM_DATA_PTR(PORT_ADDRESS + 2));
                    349:     outb_p(BYTE(&mscp, 3), OGM_DATA_PTR(PORT_ADDRESS + 3));
1.1       root      350: 
                    351:     /* Issue OGM interrupt */
1.1.1.2   root      352:     outb_p(0x1, LCL_DOORBELL_INTR(PORT_ADDRESS));
                    353: 
                    354:     ultrastor_done = done;
                    355: 
                    356: #if (ULTRASTOR_DEBUG & UD_COMMAND)
                    357:     printk("US14F: queuecommand: returning\n");
                    358: #endif
                    359: 
                    360:     return 0;
                    361: }
                    362: 
1.1.1.3 ! root      363: #ifdef NO_QUEUEING
1.1.1.2   root      364: int ultrastor_14f_command(unsigned char target, const void *cmnd,
                    365:                          void *buff, int bufflen)
                    366: {
                    367:     unsigned char in_byte;
                    368: 
                    369: #if (ULTRASTOR_DEBUG & UD_COMMAND)
                    370:     printk("US14F: command: called\n");
                    371: #endif
                    372: 
                    373:     (void)ultrastor_14f_queuecommand(target, cmnd, buff, bufflen, 0);
1.1       root      374: 
                    375:     /* Wait for ICM interrupt */
                    376:     do
1.1.1.2   root      377:        in_byte = inb_p(SYS_DOORBELL_INTR(PORT_ADDRESS));
1.1       root      378:     while (!aborted && !(in_byte & 1));
1.1.1.3 ! root      379:     if (aborted) {
        !           380: #if (ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT))
        !           381:        printk("US14F: command: aborted\n");
        !           382: #endif
1.1       root      383:        /* ??? is this right? */
                    384:        return (aborted << 16);
1.1.1.3 ! root      385:     }
1.1       root      386: 
                    387:     /* Clean ICM slot (set ICMINT bit to 0) */
1.1.1.2   root      388:     outb_p(0x1, SYS_DOORBELL_INTR(PORT_ADDRESS));
                    389: 
                    390: #if (ULTRASTOR_DEBUG & UD_COMMAND)
                    391:     printk("US14F: command: returning %08X\n",
                    392:           (mscp.adapter_status << 16) | mscp.target_status);
                    393: #endif
1.1       root      394: 
                    395:     /* ??? not right, but okay for now? */
                    396:     return (mscp.adapter_status << 16) | mscp.target_status;
                    397: }
1.1.1.2   root      398: #endif
1.1       root      399: 
                    400: int ultrastor_14f_abort(int code)
                    401: {
1.1.1.3 ! root      402: #if (ULTRASTOR_DEBUG & UD_ABORT)
        !           403:     printk("US14F: abort: called\n");
        !           404: #endif
        !           405: 
1.1       root      406:     aborted = (code ? code : DID_ABORT);
1.1.1.3 ! root      407: 
        !           408: #if (ULTRASTOR_DEBUG & UD_ABORT)
        !           409:     printk("US14F: abort: returning\n");
        !           410: #endif
        !           411: 
1.1       root      412:     return 0;
                    413: }
                    414: 
                    415: int ultrastor_14f_reset(void)
                    416: {
                    417:     unsigned char in_byte;
                    418: 
1.1.1.2   root      419: #if (ULTRASTOR_DEBUG & UD_RESET)
                    420:     printk("US14F: reset: called\n");
1.1       root      421: #endif
                    422: 
                    423:     /* Issue SCSI BUS reset */
1.1.1.2   root      424:     outb_p(0x20, LCL_DOORBELL_INTR(PORT_ADDRESS));
                    425: 
1.1       root      426:     /* Wait for completion... */
                    427:     do
1.1.1.2   root      428:        in_byte = inb_p(LCL_DOORBELL_INTR(PORT_ADDRESS));
1.1       root      429:     while (in_byte & 0x20);
                    430: 
                    431:     aborted = DID_RESET;
                    432: 
1.1.1.2   root      433: #if (ULTRASTOR_DEBUG & UD_RESET)
                    434:     printk("US14F: reset: returning\n");
1.1       root      435: #endif
                    436:     return 0;
                    437: }
                    438: 
1.1.1.3 ! root      439: #ifndef NO_QUEUEING
1.1.1.2   root      440: void ultrastor_interrupt_service(void)
                    441: {
1.1.1.3 ! root      442: #if (ULTRASTOR_DEBUG & UD_INTERRUPT)
        !           443:     printk("US14F: interrupt_service: called: status = %08X\n",
1.1.1.2   root      444:           (mscp.adapter_status << 16) | mscp.target_status);
1.1.1.3 ! root      445: #endif
        !           446: 
        !           447:     if (ultrastor_done == 0)
        !           448:        panic("US14F: interrupt_service: unexpected interrupt!\n");
        !           449:     else {
        !           450:        void (*done)(int, int);
        !           451: 
        !           452:        /* Save ultrastor_done locally and zero before calling.  This is needed
        !           453:           as once we call done, we may get another command queued before this
        !           454:           interrupt service routine can return. */
        !           455:        done = ultrastor_done;
        !           456:        ultrastor_done = 0;
        !           457: 
        !           458:        /* Clean ICM slot (set ICMINT bit to 0) */
        !           459:        outb_p(0x1, SYS_DOORBELL_INTR(PORT_ADDRESS));
        !           460: 
        !           461:        /* Let the higher levels know that we're done */
        !           462:        /* ??? status is wrong here... */
        !           463:        done(host_number, (mscp.adapter_status << 16) | mscp.target_status);
        !           464:     }
        !           465: 
        !           466: #if (ULTRASTOR_DEBUG & UD_INTERRUPT)
        !           467:     printk("US14F: interrupt_service: returning\n");
        !           468: #endif
1.1.1.2   root      469: }
                    470: 
                    471: __asm__("
                    472: _ultrastor_interrupt:
                    473:        cld
                    474:        pushl %eax
                    475:        pushl %ecx
                    476:        pushl %edx
                    477:        push %ds
                    478:        push %es
                    479:        push %fs
                    480:        movl $0x10,%eax
                    481:        mov %ax,%ds
                    482:        mov %ax,%es
                    483:        movl $0x17,%eax
                    484:        mov %ax,%fs
                    485:        movb $0x20,%al
                    486:        outb %al,$0xA0          # EOI to interrupt controller #1
                    487:        outb %al,$0x80          # give port chance to breathe
                    488:        outb %al,$0x80
                    489:        outb %al,$0x80
                    490:        outb %al,$0x80
                    491:        outb %al,$0x20
                    492:        call _ultrastor_interrupt_service
                    493:        pop %fs
                    494:        pop %es
                    495:        pop %ds
                    496:        popl %edx
                    497:        popl %ecx
                    498:        popl %eax
                    499:        iret
                    500: ");
                    501: #endif
                    502: 
1.1       root      503: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.