devroot: Use dirtab's length instead of rootdata's size
[akaros.git] / kern / drivers / dev / sdscsi.c
index 380064c..060e683 100644 (file)
@@ -7,25 +7,29 @@
  * in the LICENSE file.
  */
 
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "../port/error.h"
-
-#include "../port/sd.h"
-
-static int
-scsitest(SDreq* r)
+#include <vfs.h>
+
+#include <assert.h>
+#include <cpio.h>
+#include <error.h>
+#include <ip.h>
+#include <kfs.h>
+#include <kmalloc.h>
+#include <kref.h>
+#include <pmap.h>
+#include <sd.h>
+#include <slab.h>
+#include <smp.h>
+#include <stdio.h>
+#include <string.h>
+
+static int scsitest(struct sdreq *r)
 {
        r->write = 0;
        memset(r->cmd, 0, sizeof(r->cmd));
-       r->cmd[1] = r->lun<<5;
+       r->cmd[1] = r->lun << 5;
        r->clen = 6;
-       r->data = nil;
+       r->data = NULL;
        r->dlen = 0;
        r->flags = 0;
 
@@ -34,49 +38,49 @@ scsitest(SDreq* r)
        return r->unit->dev->ifc->rio(r);
 }
 
-int
-scsiverify(SDunit* unit)
+int scsiverify(struct sdunit *unit)
 {
-       SDreq *r;
+       struct sdreq *r;
        int i, status;
        uint8_t *inquiry;
 
-       if((r = malloc(sizeof(SDreq))) == nil)
+       r = kzmalloc(sizeof(struct sdreq), 0);
+       if (r == NULL)
                return 0;
-       if((inquiry = sdmalloc(sizeof(unit->inquiry))) == nil){
-               free(r);
+       inquiry = kzmalloc(sizeof(unit->inquiry), MEM_WAIT);
+       if (inquiry == NULL) {
+               kfree(r);
                return 0;
        }
        r->unit = unit;
-       r->lun = 0;             /* ??? */
+       r->lun = 0; /* ??? */
 
        memset(unit->inquiry, 0, sizeof(unit->inquiry));
        r->write = 0;
        r->cmd[0] = 0x12;
-       r->cmd[1] = r->lun<<5;
-       r->cmd[4] = sizeof(unit->inquiry)-1;
+       r->cmd[1] = r->lun << 5;
+       r->cmd[4] = sizeof(unit->inquiry) - 1;
        r->clen = 6;
        r->data = inquiry;
-       r->dlen = sizeof(unit->inquiry)-1;
+       r->dlen = sizeof(unit->inquiry) - 1;
        r->flags = 0;
 
        r->status = ~0;
-       if(unit->dev->ifc->rio(r) != SDok){
-               free(r);
+       if (unit->dev->ifc->rio(r) != SDok) {
+               kfree(r);
                return 0;
        }
        memmove(unit->inquiry, inquiry, r->dlen);
-       free(inquiry);
+       kfree(inquiry);
 
-       SET(status);
-       for(i = 0; i < 3; i++){
-               while((status = scsitest(r)) == SDbusy)
+       for (i = 0; i < 3; i++) {
+               while ((status = scsitest(r)) == SDbusy)
                        ;
-               if(status == SDok || status != SDcheck)
+               if (status == SDok || status != SDcheck)
                        break;
-               if(!(r->flags & SDvalidsense))
+               if (!(r->flags & SDvalidsense))
                        break;
-               if((r->sense[2] & 0x0F) != 0x02)
+               if ((r->sense[2] & 0x0F) != 0x02)
                        continue;
 
                /*
@@ -87,29 +91,29 @@ scsiverify(SDunit* unit)
                 * If there's no medium, that's OK too, but don't
                 * try to spin it up.
                 */
-               if(r->sense[12] == 0x04){
-                       if(r->sense[13] == 0x02 || r->sense[13] == 0x01){
+               if (r->sense[12] == 0x04) {
+                       if (r->sense[13] == 0x02 || r->sense[13] == 0x01) {
                                status = SDok;
                                break;
                        }
                }
-               if(r->sense[12] == 0x3A)
+               if (r->sense[12] == 0x3A)
                        break;
        }
 
-       if(status == SDok){
+       if (status == SDok) {
                /*
                 * Try to ensure a direct-access device is spinning.
                 * Don't wait for completion, ignore the result.
                 */
-               if((unit->inquiry[0] & SDinq0periphtype) == SDperdisk){
+               if ((unit->inquiry[0] & SDinq0periphtype) == SDperdisk) {
                        memset(r->cmd, 0, sizeof(r->cmd));
                        r->write = 0;
                        r->cmd[0] = 0x1B;
-                       r->cmd[1] = (r->lun<<5)|0x01;
+                       r->cmd[1] = (r->lun << 5) | 0x01;
                        r->cmd[4] = 1;
                        r->clen = 6;
-                       r->data = nil;
+                       r->data = NULL;
                        r->dlen = 0;
                        r->flags = 0;
 
@@ -117,17 +121,16 @@ scsiverify(SDunit* unit)
                        unit->dev->ifc->rio(r);
                }
        }
-       free(r);
+       kfree(r);
 
-       if(status == SDok || status == SDcheck)
+       if (status == SDok || status == SDcheck)
                return 1;
        return 0;
 }
 
-static int
-scsirio(SDreq* r)
+static int scsirio(struct sdreq *r)
 {
-       Proc *up = externup();
+       ERRSTACK(1);
        /*
         * Perform an I/O request, returning
         *      -1      failure
@@ -138,40 +141,40 @@ scsirio(SDreq* r)
         * caller should re-initialise if necesary.
         */
        r->status = ~0;
-       switch(r->unit->dev->ifc->rio(r)){
+       switch (r->unit->dev->ifc->rio(r)) {
        default:
                break;
        case SDcheck:
-               if(!(r->flags & SDvalidsense))
+               if (!(r->flags & SDvalidsense))
                        break;
-               switch(r->sense[2] & 0x0F){
-               case 0x00:              /* no sense */
-               case 0x01:              /* recovered error */
+               switch (r->sense[2] & 0x0F) {
+               case 0x00: /* no sense */
+               case 0x01: /* recovered error */
                        return 2;
-               case 0x06:              /* check condition */
+               case 0x06: /* check condition */
                        /*
                         * 0x28 - not ready to ready transition,
                         *        medium may have changed.
                         * 0x29 - power on or some type of reset.
                         */
-                       if(r->sense[12] == 0x28 && r->sense[13] == 0)
+                       if (r->sense[12] == 0x28 && r->sense[13] == 0)
                                return 2;
-                       if(r->sense[12] == 0x29)
+                       if (r->sense[12] == 0x29)
                                return 2;
                        break;
-               case 0x02:              /* not ready */
+               case 0x02: /* not ready */
                        /*
                         * If no medium present, bail out.
                         * If unit is becoming ready, rather than not
                         * not ready, wait a little then poke it again.                                  */
-                       if(r->sense[12] == 0x3A)
+                       if (r->sense[12] == 0x3A)
                                break;
-                       if(r->sense[12] != 0x04 || r->sense[13] != 0x01)
+                       if (r->sense[12] != 0x04 || r->sense[13] != 0x01)
                                break;
 
-                       while(waserror())
+                       while (waserror())
                                ;
-                       tsleep(&up->sleep, return0, 0, 500);
+                       kthread_usleep(500 * 1000);
                        poperror();
                        scsitest(r);
                        return 2;
@@ -185,25 +188,26 @@ scsirio(SDreq* r)
        return -1;
 }
 
-int
-scsionline(SDunit* unit)
+int scsionline(struct sdunit *unit)
 {
-       SDreq *r;
+       struct sdreq *r;
        uint8_t *p;
        int ok, retries;
 
-       if((r = malloc(sizeof(SDreq))) == nil)
+       r = kzmalloc(sizeof(struct sdreq), 0);
+       if (r == NULL)
                return 0;
-       if((p = sdmalloc(8)) == nil){
-               free(r);
+       p = kzmalloc(8, 0);
+       if (p == NULL) {
+               kfree(r);
                return 0;
        }
 
        ok = 0;
 
        r->unit = unit;
-       r->lun = 0;                             /* ??? */
-       for(retries = 0; retries < 10; retries++){
+       r->lun = 0; /* ??? */
+       for (retries = 0; retries < 10; retries++) {
                /*
                 * Read-capacity is mandatory for DA, WORM, CD-ROM and
                 * MO. It may return 'not ready' if type DA is not
@@ -213,26 +217,26 @@ scsionline(SDunit* unit)
                r->write = 0;
                memset(r->cmd, 0, sizeof(r->cmd));
                r->cmd[0] = 0x25;
-               r->cmd[1] = r->lun<<5;
+               r->cmd[1] = r->lun << 5;
                r->clen = 10;
                r->data = p;
                r->dlen = 8;
                r->flags = 0;
 
                r->status = ~0;
-               switch(scsirio(r)){
+               switch (scsirio(r)) {
                default:
                        break;
                case 0:
-                       unit->sectors = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
-                       unit->secsize = (p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7];
+                       unit->sectors = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+                       unit->secsize = (p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7];
 
                        /*
                         * Some ATAPI CD readers lie about the block size.
                         * Since we don't read audio via this interface
                         * it's okay to always fudge this.
                         */
-                       if(unit->secsize == 2352)
+                       if (unit->secsize == 2352)
                                unit->secsize = 2048;
                        /*
                         * Devices with removable media may return 0 sectors
@@ -242,7 +246,7 @@ scsionline(SDunit* unit)
                         * Read-capacity returns the LBA of the last sector,
                         * therefore the number of sectors must be incremented.
                         */
-                       if(unit->sectors != 0)
+                       if (unit->sectors != 0)
                                unit->sectors++;
                        ok = 1;
                        break;
@@ -254,31 +258,31 @@ scsionline(SDunit* unit)
                }
                break;
        }
-       free(p);
-       free(r);
+       kfree(p);
+       kfree(r);
 
-       if(ok)
-               return ok+retries;
+       if (ok)
+               return ok + retries;
        else
                return 0;
 }
 
-int
-scsiexec(SDunit* unit, int write, uint8_t* cmd, int clen, void* data,
-        int* dlen)
+int scsiexec(struct sdunit *unit, int write, uint8_t *cmd, int clen, void *data,
+             int *dlen)
 {
-       SDreq *r;
+       struct sdreq *r;
        int status;
 
-       if((r = malloc(sizeof(SDreq))) == nil)
+       r = kzmalloc(sizeof(struct sdreq), 0);
+       if (r == NULL)
                return SDmalloc;
        r->unit = unit;
-       r->lun = cmd[1]>>5;             /* ??? */
+       r->lun = cmd[1] >> 5; /* ??? */
        r->write = write;
        memmove(r->cmd, cmd, clen);
        r->clen = clen;
        r->data = data;
-       if(dlen)
+       if (dlen)
                r->dlen = *dlen;
        r->flags = 0;
 
@@ -289,13 +293,13 @@ scsiexec(SDunit* unit, int write, uint8_t* cmd, int clen, void* data,
         * There should be no calls to 'error()' below this
         * which percolate back up.
         */
-       switch(status = unit->dev->ifc->rio(r)){
+       switch (status = unit->dev->ifc->rio(r)) {
        case SDok:
-               if(dlen)
+               if (dlen)
                        *dlen = r->rlen;
-               /*FALLTHROUGH*/
+       /*FALLTHROUGH*/
        case SDcheck:
-               /*FALLTHROUGH*/
+       /*FALLTHROUGH*/
        default:
                /*
                 * It's more complicated than this. There are conditions
@@ -309,56 +313,56 @@ scsiexec(SDunit* unit, int write, uint8_t* cmd, int clen, void* data,
                 */
                break;
        }
-       sdfree(r);
+       kfree(r);
 
        return status;
 }
 
-static void
-scsifmt10(SDreq *r, int write, int lun, uint32_t nb, uint64_t bno)
+static void scsifmt10(struct sdreq *r, int write, int lun, uint32_t nb,
+                      uint64_t bno)
 {
        uint8_t *c;
 
        c = r->cmd;
-       if(write == 0)
+       if (write == 0)
                c[0] = 0x28;
        else
                c[0] = 0x2A;
-       c[1] = lun<<5;
-       c[2] = bno>>24;
-       c[3] = bno>>16;
-       c[4] = bno>>8;
+       c[1] = lun << 5;
+       c[2] = bno >> 24;
+       c[3] = bno >> 16;
+       c[4] = bno >> 8;
        c[5] = bno;
        c[6] = 0;
-       c[7] = nb>>8;
+       c[7] = nb >> 8;
        c[8] = nb;
        c[9] = 0;
 
        r->clen = 10;
 }
 
-static void
-scsifmt16(SDreq *r, int write, int lun, uint32_t nb, uint64_t bno)
+static void scsifmt16(struct sdreq *r, int write, int lun, uint32_t nb,
+                      uint64_t bno)
 {
        uint8_t *c;
 
        c = r->cmd;
-       if(write == 0)
+       if (write == 0)
                c[0] = 0x88;
        else
                c[0] = 0x8A;
-       c[1] = lun<<5;          /* so wrong */
-       c[2] = bno>>56;
-       c[3] = bno>>48;
-       c[4] = bno>>40;
-       c[5] = bno>>32;
-       c[6] = bno>>24;
-       c[7] = bno>>16;
-       c[8] = bno>>8;
+       c[1] = lun << 5; /* so wrong */
+       c[2] = bno >> 56;
+       c[3] = bno >> 48;
+       c[4] = bno >> 40;
+       c[5] = bno >> 32;
+       c[6] = bno >> 24;
+       c[7] = bno >> 16;
+       c[8] = bno >> 8;
        c[9] = bno;
-       c[10] = nb>>24;
-       c[11] = nb>>16;
-       c[12] = nb>>8;
+       c[10] = nb >> 24;
+       c[11] = nb >> 16;
+       c[12] = nb >> 8;
        c[13] = nb;
        c[14] = 0;
        c[15] = 0;
@@ -366,29 +370,29 @@ scsifmt16(SDreq *r, int write, int lun, uint32_t nb, uint64_t bno)
        r->clen = 16;
 }
 
-int32_t
-scsibio(SDunit* unit, int lun, int write, void* data, int32_t nb,
-       uint64_t bno)
+int32_t scsibio(struct sdunit *unit, int lun, int write, void *data, int32_t nb,
+                uint64_t bno)
 {
-       SDreq *r;
+       struct sdreq *r;
        int32_t rlen;
 
-       if((r = malloc(sizeof(SDreq))) == nil)
-               error(Enomem);
+       r = kzmalloc(sizeof(struct sdreq), 0);
+       if (r == NULL)
+               error(ENOMEM, "scsibio: can't allocate %d bytes", sizeof(*r));
        r->unit = unit;
        r->lun = lun;
 again:
        r->write = write;
-       if(bno >= (1ULL<<32))
+       if (bno >= (1ULL << 32))
                scsifmt16(r, write, lun, nb, bno);
        else
                scsifmt10(r, write, lun, nb, bno);
        r->data = data;
-       r->dlen = nb*unit->secsize;
+       r->dlen = nb * unit->secsize;
        r->flags = 0;
 
        r->status = ~0;
-       switch(scsirio(r)){
+       switch (scsirio(r)) {
        default:
                rlen = -1;
                break;
@@ -397,40 +401,39 @@ again:
                break;
        case 2:
                rlen = -1;
-               if(!(r->flags & SDvalidsense))
+               if (!(r->flags & SDvalidsense))
                        break;
-               switch(r->sense[2] & 0x0F){
+               switch (r->sense[2] & 0x0F) {
                default:
                        break;
-               case 0x01:              /* recovered error */
-                       print("%s: recovered error at sector %llu\n",
-                               unit->SDperm.name, bno);
+               case 0x01: /* recovered error */
+                       printd("%s: recovered error at sector %llu\n", unit->SDperm.name,
+                              bno);
                        rlen = r->rlen;
                        break;
-               case 0x06:              /* check condition */
+               case 0x06: /* check condition */
                        /*
                         * Check for a removeable media change.
                         * If so, mark it by zapping the geometry info
                         * to force an online request.
                         */
-                       if(r->sense[12] != 0x28 || r->sense[13] != 0)
+                       if (r->sense[12] != 0x28 || r->sense[13] != 0)
                                break;
-                       if(unit->inquiry[1] & SDinq1removable)
+                       if (unit->inquiry[1] & SDinq1removable)
                                unit->sectors = 0;
                        break;
-               case 0x02:              /* not ready */
+               case 0x02: /* not ready */
                        /*
                         * If unit is becoming ready,
                         * rather than not not ready, try again.
                         */
-                       if(r->sense[12] == 0x04 && r->sense[13] == 0x01)
+                       if (r->sense[12] == 0x04 && r->sense[13] == 0x01)
                                goto again;
                        break;
                }
                break;
        }
-       free(r);
+       kfree(r);
 
        return rlen;
 }
-